home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / misc2.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-26  |  119.9 KB  |  5,186 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * misc2.c: Various functions.
  12.  */
  13. #include "vim.h"
  14.  
  15. #ifdef HAVE_FCNTL_H
  16. # include <fcntl.h>        /* for chdir() */
  17. #endif
  18.  
  19. #if defined(FEAT_VIRTUALEDIT) || defined(PROTO)
  20. static int coladvance2 __ARGS((pos_T *pos, int addspaces, int finetune, colnr_T wcol));
  21.  
  22. /*
  23.  * Return TRUE if in the current mode we need to use virtual.
  24.  */
  25.     int
  26. virtual_active()
  27. {
  28.     return (ve_flags == VE_ALL
  29. # ifdef FEAT_VISUAL
  30.         || ((ve_flags & VE_BLOCK) && VIsual_active && VIsual_mode == Ctrl_V)
  31. # endif
  32.         || ((ve_flags & VE_INSERT) && (State & INSERT)));
  33. }
  34.  
  35. /*
  36.  * Get the screen position of the cursor.
  37.  */
  38.     int
  39. getviscol()
  40. {
  41.     int        x = 0;
  42.     char_u    *line = ml_get_curline();
  43.     char_u    *p;
  44.  
  45.     for (p = line; (colnr_T)(p - line) < curwin->w_cursor.col; )
  46.     x += lbr_chartabsize_adv(&p, x);
  47.  
  48.     return x + curwin->w_cursor.coladd;
  49. }
  50.  
  51. /*
  52.  * Get the screen position of character col with a coladd.
  53.  */
  54.     int
  55. getviscol2(col, coladd)
  56.     colnr_T    col;
  57.     colnr_T    coladd;
  58. {
  59.     int        x = 0;
  60.     char_u    *line = ml_get_curline();
  61.     char_u    *p;
  62.  
  63.     for (p = line; (colnr_T)(p - line) < col; )
  64.     x += lbr_chartabsize_adv(&p, x);
  65.  
  66.     return x + coladd;
  67. }
  68.  
  69. /*
  70.  * Go to column "wcol", and add/insert white space as neccessary to get the
  71.  * cursor in that column.
  72.  * The caller must have saved the cursor line for undo!
  73.  */
  74.     int
  75. coladvance_force(wcol)
  76.     colnr_T wcol;
  77. {
  78.     int rc = coladvance2(&curwin->w_cursor, TRUE, FALSE, wcol);
  79.  
  80.     if (wcol == MAXCOL)
  81.     curwin->w_valid &= ~VALID_VIRTCOL;
  82.     else
  83.     {
  84.     /* Virtcol is valid */
  85.     curwin->w_valid |= VALID_VIRTCOL;
  86.     curwin->w_virtcol = wcol;
  87.     }
  88.     return rc;
  89. }
  90. #endif
  91.  
  92. /*
  93.  * Try to advance the Cursor to the specified column.
  94.  * If virtual editing: fine tune the cursor position.
  95.  * Note that all virtual positions off the end of a line should share
  96.  * a curwin->w_cursor.col value (n.b. this is equal to STRLEN(line)),
  97.  * beginning at coladd 0.
  98.  *
  99.  * return OK if desired column is reached, FAIL if not
  100.  */
  101.     int
  102. coladvance(wcol)
  103.     colnr_T    wcol;
  104. {
  105.     int rc = getvpos(&curwin->w_cursor, wcol);
  106.  
  107.     if (wcol == MAXCOL)
  108.     curwin->w_valid &= ~VALID_VIRTCOL;
  109.     else
  110.     {
  111.     /* Virtcol is valid */
  112.     curwin->w_valid |= VALID_VIRTCOL;
  113.     curwin->w_virtcol = wcol;
  114.     }
  115.     return rc;
  116. }
  117.  
  118.     int
  119. getvpos(pos, wcol)
  120.     pos_T   *pos;
  121.     colnr_T wcol;
  122. {
  123. #ifdef FEAT_VIRTUALEDIT
  124.     return coladvance2(pos, FALSE, virtual_active(), wcol);
  125. }
  126.  
  127.     static int
  128. coladvance2(pos, addspaces, finetune, wcol)
  129.     pos_T    *pos;
  130.     int        addspaces;    /* change the text to achieve our goal? */
  131.     int        finetune;    /* change char offset for the excact column */
  132.     colnr_T    wcol;        /* column to move to */
  133. {
  134. #endif
  135.     int        idx;
  136.     char_u    *ptr;
  137.     char_u    *line;
  138.     colnr_T    col = 0;
  139.     int        csize = 0;
  140.     int        one_more;
  141.  
  142.     one_more = (State & INSERT) || restart_edit != NUL
  143. #ifdef FEAT_VISUAL
  144.                       || (VIsual_active && *p_sel != 'o')
  145. #endif
  146.                       ;
  147.     line = ml_get_curline();
  148.  
  149.     /* The difference between wcol and col will be used to set coladd
  150.      * and insert spaces.
  151.      */
  152.     if (wcol >= MAXCOL)
  153.     {
  154.         idx = (int)STRLEN(line) - 1 + one_more;
  155.         col = wcol;
  156.  
  157. #ifdef FEAT_VIRTUALEDIT
  158.         if ((addspaces || finetune) && !VIsual_active)
  159.         {
  160.         curwin->w_curswant = linetabsize(line) + one_more;
  161.         if (curwin->w_curswant > 0)
  162.             --curwin->w_curswant;
  163.         }
  164. #endif
  165.     }
  166.     else
  167.     {
  168. #ifdef FEAT_VIRTUALEDIT
  169.     int width = W_WIDTH(curwin) - win_col_off(curwin);
  170.  
  171.     if ((addspaces || finetune)
  172.         && curwin->w_p_wrap
  173. # ifdef FEAT_VERTSPLIT
  174.         && curwin->w_width != 0
  175. # endif
  176.         && wcol >= (colnr_T)width)
  177.     {
  178.         csize = linetabsize(line);
  179.         if (csize > 0)
  180.         csize--;
  181.  
  182.         if (wcol / width > (colnr_T)csize / width)
  183.         {
  184.         /* In case of line wrapping don't move the cursor beyond the
  185.          * right screen edge. */
  186.         wcol = (csize / width + 1) * width - 1;
  187.         }
  188.     }
  189. #endif
  190.  
  191.     idx = -1;
  192.     ptr = line;
  193.     while (col <= wcol && *ptr != NUL)
  194.     {
  195.         /* Count a tab for what it's worth (if list mode not on) */
  196.         csize = lbr_chartabsize_adv(&ptr, col);
  197.         col += csize;
  198.     }
  199.     idx = (int)(ptr - line);
  200.     /*
  201.      * Handle all the special cases.  The virtual_active() check
  202.      * is needed to ensure that a virtual position off the end of
  203.      * a line has the correct indexing.  The one_more comparison
  204.      * replaces an explicit add of one_more later on.
  205.      */
  206.     if (col > wcol || (!virtual_active() && one_more == 0))
  207.     {
  208.         idx -= 1;
  209.         col -= csize;
  210.     }
  211.  
  212. #ifdef FEAT_VIRTUALEDIT
  213.     if (virtual_active() && addspaces
  214.         && ((col != wcol && col != wcol + 1) || csize > 1))
  215.     {
  216.         if (line[idx] == NUL)
  217.         {
  218.         /* Append spaces */
  219.         int    correct = wcol - col;
  220.         char_u    *newline = alloc(idx + correct + 1);
  221.         int    t;
  222.  
  223.         if (newline == NULL)
  224.             return FAIL;
  225.  
  226.         for (t = 0; t < idx; ++t)
  227.             newline[t] = line[t];
  228.  
  229.         for (t = 0; t < correct; ++t)
  230.             newline[t + idx] = ' ';
  231.  
  232.         newline[idx + correct] = NUL;
  233.  
  234.         ml_replace(pos->lnum, newline, FALSE);
  235.         changed_bytes(pos->lnum, (colnr_T)idx);
  236.         idx += correct;
  237.         col = wcol;
  238.         }
  239.         else
  240.         {
  241.         /* Break a tab */
  242.         int    linelen = (int)STRLEN(line);
  243.         int    correct = wcol - col - csize + 1; /* negative!! */
  244.         char_u    *newline = alloc(linelen + csize);
  245.         int    t, s = 0;
  246.         int    v;
  247.  
  248.         /*
  249.          * break a tab
  250.          */
  251.         if (newline == NULL || -correct > csize)
  252.             return FAIL;
  253.  
  254.         for (t = 0; t < linelen; t++)
  255.         {
  256.             if (t != idx)
  257.             newline[s++] = line[t];
  258.             else
  259.             for (v = 0; v < csize; v++)
  260.                 newline[s++] = ' ';
  261.         }
  262.  
  263.         newline[linelen + csize - 1] = NUL;
  264.  
  265.         ml_replace(pos->lnum, newline, FALSE);
  266.         changed_bytes(pos->lnum, idx);
  267.         idx += (csize - 1 + correct);
  268.         col += correct;
  269.         }
  270.     }
  271. #endif
  272.     }
  273.  
  274.     if (idx < 0)
  275.     pos->col = 0;
  276.     else
  277.     pos->col = idx;
  278.  
  279. #ifdef FEAT_VIRTUALEDIT
  280.     pos->coladd = 0;
  281.  
  282.     if (finetune)
  283.     {
  284.     int a = col;
  285.     int b = wcol - a;
  286.  
  287.     /* modify the real cursor position to make the cursor appear at
  288.      * the wanted column */
  289.     if (b > 0 && b < (MAXCOL - 2 * W_WIDTH(curwin)))
  290.         pos->coladd = b;
  291.  
  292.     col += b;
  293.     }
  294. #endif
  295.  
  296. #ifdef FEAT_MBYTE
  297.     /* prevent cursor from moving on the trail byte */
  298.     if (has_mbyte)
  299.     mb_adjust_cursor();
  300. #endif
  301.  
  302.     if (col < wcol)
  303.     return FAIL;
  304.     return OK;
  305. }
  306.  
  307. /*
  308.  * inc(p)
  309.  *
  310.  * Increment the line pointer 'p' crossing line boundaries as necessary.
  311.  * Return 1 when going to the next line.
  312.  * Return 2 when moving forward onto a NUL at the end of the line).
  313.  * Return -1 when at the end of file.
  314.  * Return 0 otherwise.
  315.  */
  316.     int
  317. inc_cursor()
  318. {
  319.     return inc(&curwin->w_cursor);
  320. }
  321.  
  322.     int
  323. inc(lp)
  324.     pos_T  *lp;
  325. {
  326.     char_u  *p = ml_get_pos(lp);
  327.  
  328.     if (*p != NUL)    /* still within line, move to next char (may be NUL) */
  329.     {
  330. #ifdef FEAT_MBYTE
  331.     if (has_mbyte)
  332.     {
  333.         int l = (*mb_ptr2len_check)(p);
  334.  
  335.         lp->col += l;
  336.         return ((p[l] != NUL) ? 0 : 2);
  337.     }
  338. #endif
  339.     lp->col++;
  340. #ifdef FEAT_VIRTUALEDIT
  341.     lp->coladd = 0;
  342. #endif
  343.     return ((p[1] != NUL) ? 0 : 2);
  344.     }
  345.     if (lp->lnum != curbuf->b_ml.ml_line_count)     /* there is a next line */
  346.     {
  347.     lp->col = 0;
  348.     lp->lnum++;
  349. #ifdef FEAT_VIRTUALEDIT
  350.     lp->coladd = 0;
  351. #endif
  352.     return 1;
  353.     }
  354.     return -1;
  355. }
  356.  
  357. /*
  358.  * incl(lp): same as inc(), but skip the NUL at the end of non-empty lines
  359.  */
  360.     int
  361. incl(lp)
  362.     pos_T    *lp;
  363. {
  364.     int        r;
  365.  
  366.     if ((r = inc(lp)) >= 1 && lp->col)
  367.     r = inc(lp);
  368.     return r;
  369. }
  370.  
  371. /*
  372.  * dec(p)
  373.  *
  374.  * Decrement the line pointer 'p' crossing line boundaries as necessary.
  375.  * Return 1 when crossing a line, -1 when at start of file, 0 otherwise.
  376.  */
  377.     int
  378. dec_cursor()
  379. {
  380. #ifdef FEAT_MBYTE
  381.     return (has_mbyte ? mb_dec(&curwin->w_cursor) : dec(&curwin->w_cursor));
  382. #else
  383.     return dec(&curwin->w_cursor);
  384. #endif
  385. }
  386.  
  387.     int
  388. dec(lp)
  389.     pos_T  *lp;
  390. {
  391.     if (lp->col > 0)
  392.     {        /* still within line */
  393.     lp->col--;
  394.     return 0;
  395.     }
  396.     if (lp->lnum > 1)
  397.     {        /* there is a prior line */
  398.     lp->lnum--;
  399.     lp->col = (colnr_T)STRLEN(ml_get(lp->lnum));
  400.     return 1;
  401.     }
  402.     return -1;            /* at start of file */
  403. }
  404.  
  405. /*
  406.  * decl(lp): same as dec(), but skip the NUL at the end of non-empty lines
  407.  */
  408.     int
  409. decl(lp)
  410.     pos_T    *lp;
  411. {
  412.     int        r;
  413.  
  414.     if ((r = dec(lp)) == 1 && lp->col)
  415.     r = dec(lp);
  416.     return r;
  417. }
  418.  
  419. /*
  420.  * Make sure curwin->w_cursor.lnum is valid.
  421.  */
  422.     void
  423. check_cursor_lnum()
  424. {
  425.     if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count)
  426.     {
  427. #ifdef FEAT_FOLDING
  428.     /* If there is a closed fold at the end of the file, put the cursor in
  429.      * its first line.  Otherwise in the last line. */
  430.     if (!hasFolding(curbuf->b_ml.ml_line_count,
  431.                         &curwin->w_cursor.lnum, NULL))
  432. #endif
  433.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  434.     }
  435.     if (curwin->w_cursor.lnum <= 0)
  436.     curwin->w_cursor.lnum = 1;
  437. }
  438.  
  439. /*
  440.  * Make sure curwin->w_cursor.col is valid.
  441.  */
  442.     void
  443. check_cursor_col()
  444. {
  445.     colnr_T len;
  446. #ifdef FEAT_VIRTUALEDIT
  447.     colnr_T oldcol = curwin->w_cursor.col + curwin->w_cursor.coladd;
  448. #endif
  449.  
  450.     len = (colnr_T)STRLEN(ml_get_curline());
  451.     if (len == 0)
  452.     curwin->w_cursor.col = 0;
  453.     else if (curwin->w_cursor.col >= len)
  454.     {
  455.     /* Allow cursor past end-of-line in Insert mode, restarting Insert
  456.      * mode or when in Visual mode and 'selection' isn't "old" */
  457.     if (State & INSERT || restart_edit
  458. #ifdef FEAT_VISUAL
  459.         || (VIsual_active && *p_sel != 'o')
  460. #endif
  461.         || virtual_active())
  462.         curwin->w_cursor.col = len;
  463.     else
  464.         curwin->w_cursor.col = len - 1;
  465.     }
  466.  
  467. #ifdef FEAT_VIRTUALEDIT
  468.     /* If virtual editing is on, we can leave the cursor on the old position,
  469.      * only we must set it to virtual.  But don't do it when at the end of the
  470.      * line. */
  471.     if (oldcol == MAXCOL)
  472.     curwin->w_cursor.coladd = 0;
  473.     else if (ve_flags == VE_ALL)
  474.     curwin->w_cursor.coladd = oldcol - curwin->w_cursor.col;
  475. #endif
  476. }
  477.  
  478. /*
  479.  * make sure curwin->w_cursor in on a valid character
  480.  */
  481.     void
  482. check_cursor()
  483. {
  484.     check_cursor_lnum();
  485.     check_cursor_col();
  486. }
  487.  
  488. #if defined(FEAT_TEXTOBJ) || defined(PROTO)
  489. /*
  490.  * Make sure curwin->w_cursor is not on the NUL at the end of the line.
  491.  * Allow it when in Visual mode and 'selection' is not "old".
  492.  */
  493.     void
  494. adjust_cursor_col()
  495. {
  496.     if (curwin->w_cursor.col > 0
  497. # ifdef FEAT_VISUAL
  498.         && (!VIsual_active || *p_sel == 'o')
  499. # endif
  500.         && gchar_cursor() == NUL)
  501.     --curwin->w_cursor.col;
  502. }
  503. #endif
  504.  
  505. /*
  506.  * When curwin->w_leftcol has changed, adjust the cursor position.
  507.  * Return TRUE if the cursor was moved.
  508.  */
  509.     int
  510. leftcol_changed()
  511. {
  512.     long    lastcol;
  513.     colnr_T    s, e;
  514.     int        retval = FALSE;
  515.  
  516.     changed_cline_bef_curs();
  517.     lastcol = curwin->w_leftcol + W_WIDTH(curwin) - curwin_col_off() - 1;
  518.     validate_virtcol();
  519.  
  520.     /*
  521.      * If the cursor is right or left of the screen, move it to last or first
  522.      * character.
  523.      */
  524.     if (curwin->w_virtcol > (colnr_T)(lastcol - p_siso))
  525.     {
  526.     retval = TRUE;
  527.     coladvance((colnr_T)(lastcol - p_siso));
  528.     }
  529.     else if (curwin->w_virtcol < curwin->w_leftcol + p_siso)
  530.     {
  531.     retval = TRUE;
  532.     (void)coladvance((colnr_T)(curwin->w_leftcol + p_siso));
  533.     }
  534.  
  535.     /*
  536.      * If the start of the character under the cursor is not on the screen,
  537.      * advance the cursor one more char.  If this fails (last char of the
  538.      * line) adjust the scrolling.
  539.      */
  540.     getvcol(curwin, &curwin->w_cursor, &s, NULL, &e);
  541.     if (e > (colnr_T)lastcol)
  542.     {
  543.     retval = TRUE;
  544.     coladvance(s - 1);
  545.     }
  546.     else if (s < curwin->w_leftcol)
  547.     {
  548.     retval = TRUE;
  549.     if (coladvance(e + 1) == FAIL)    /* there isn't another character */
  550.     {
  551.         curwin->w_leftcol = s;    /* adjust w_leftcol instead */
  552.         changed_cline_bef_curs();
  553.     }
  554.     }
  555.  
  556.     if (retval)
  557.     curwin->w_set_curswant = TRUE;
  558.     redraw_later(NOT_VALID);
  559.     return retval;
  560. }
  561.  
  562. /**********************************************************************
  563.  * Various routines dealing with allocation and deallocation of memory.
  564.  */
  565.  
  566. #if defined(MEM_PROFILE) || defined(PROTO)
  567.  
  568. # define MEM_SIZES  8200
  569. static long_u mem_allocs[MEM_SIZES];
  570. static long_u mem_frees[MEM_SIZES];
  571. static long_u mem_allocated;
  572. static long_u mem_freed;
  573. static long_u mem_peak;
  574. static long_u num_alloc;
  575. static long_u num_freed;
  576.  
  577. static void mem_pre_alloc_s __ARGS((size_t *sizep));
  578. static void mem_pre_alloc_l __ARGS((long_u *sizep));
  579. static void mem_post_alloc __ARGS((void **pp, size_t size));
  580. static void mem_pre_free __ARGS((void **pp));
  581.  
  582.     static void
  583. mem_pre_alloc_s(sizep)
  584.     size_t *sizep;
  585. {
  586.     *sizep += sizeof(size_t);
  587. }
  588.  
  589.     static void
  590. mem_pre_alloc_l(sizep)
  591.     long_u *sizep;
  592. {
  593.     *sizep += sizeof(size_t);
  594. }
  595.  
  596.     static void
  597. mem_post_alloc(pp, size)
  598.     void **pp;
  599.     size_t size;
  600. {
  601.     if (*pp == NULL)
  602.     return;
  603.     size -= sizeof(size_t);
  604.     *(long_u *)*pp = size;
  605.     if (size <= MEM_SIZES-1)
  606.     mem_allocs[size-1]++;
  607.     else
  608.     mem_allocs[MEM_SIZES-1]++;
  609.     mem_allocated += size;
  610.     if (mem_allocated - mem_freed > mem_peak)
  611.     mem_peak = mem_allocated - mem_freed;
  612.     num_alloc++;
  613.     *pp = (void *)((char *)*pp + sizeof(size_t));
  614. }
  615.  
  616.     static void
  617. mem_pre_free(pp)
  618.     void **pp;
  619. {
  620.     long_u size;
  621.  
  622.     *pp = (void *)((char *)*pp - sizeof(size_t));
  623.     size = *(size_t *)*pp;
  624.     if (size <= MEM_SIZES-1)
  625.     mem_frees[size-1]++;
  626.     else
  627.     mem_frees[MEM_SIZES-1]++;
  628.     mem_freed += size;
  629.     num_freed++;
  630. }
  631.  
  632. /*
  633.  * called on exit via atexit()
  634.  */
  635.     void
  636. vim_mem_profile_dump()
  637. {
  638.     int i, j;
  639.  
  640.     printf("\r\n");
  641.     j = 0;
  642.     for (i = 0; i < MEM_SIZES - 1; i++)
  643.     {
  644.     if (mem_allocs[i] || mem_frees[i])
  645.     {
  646.         if (mem_frees[i] > mem_allocs[i])
  647.         printf("\r\n%s", _("ERROR: "));
  648.         printf("[%4d / %4lu-%-4lu] ", i + 1, mem_allocs[i], mem_frees[i]);
  649.         j++;
  650.         if (j > 3)
  651.         {
  652.         j = 0;
  653.         printf("\r\n");
  654.         }
  655.     }
  656.     }
  657.  
  658.     i = MEM_SIZES - 1;
  659.     if (mem_allocs[i])
  660.     {
  661.     printf("\r\n");
  662.     if (mem_frees[i] > mem_allocs[i])
  663.         printf(_("ERROR: "));
  664.     printf("[>%d / %4lu-%-4lu]", i, mem_allocs[i], mem_frees[i]);
  665.     }
  666.  
  667.     printf(_("\n[bytes] total alloc-freed %lu-%lu, in use %lu, peak use %lu\n"),
  668.         mem_allocated, mem_freed, mem_allocated - mem_freed, mem_peak);
  669.     printf(_("[calls] total re/malloc()'s %lu, total free()'s %lu\n\n"),
  670.         num_alloc, num_freed);
  671. }
  672.  
  673. #endif /* MEM_PROFILE */
  674.  
  675. /*
  676.  * Some memory is reserved for error messages and for being able to
  677.  * call mf_release_all(), which needs some memory for mf_trans_add().
  678.  */
  679. #if defined(MSDOS) && !defined(DJGPP)
  680. # define SMALL_MEM
  681. # define KEEP_ROOM 8192L
  682. #else
  683. # define KEEP_ROOM (2 * 8192L)
  684. #endif
  685.  
  686. /*
  687.  * Note: if unsinged is 16 bits we can only allocate up to 64K with alloc().
  688.  * Use lalloc for larger blocks.
  689.  */
  690.     char_u *
  691. alloc(size)
  692.     unsigned        size;
  693. {
  694.     return (lalloc((long_u)size, TRUE));
  695. }
  696.  
  697. /*
  698.  * Allocate memory and set all bytes to zero.
  699.  */
  700.     char_u *
  701. alloc_clear(size)
  702.     unsigned        size;
  703. {
  704.     char_u *p;
  705.  
  706.     p = (lalloc((long_u)size, TRUE));
  707.     if (p != NULL)
  708.     (void)vim_memset(p, 0, (size_t)size);
  709.     return p;
  710. }
  711.  
  712. /*
  713.  * alloc() with check for maximum line length
  714.  */
  715.     char_u *
  716. alloc_check(size)
  717.     unsigned        size;
  718. {
  719. #if !defined(UNIX) && !defined(__EMX__)
  720.     if (sizeof(int) == 2 && size > 0x7fff)
  721.     {
  722.     /* Don't hide this message */
  723.     emsg_silent = 0;
  724.     EMSG(_("E340: Line is becoming too long"));
  725.     return NULL;
  726.     }
  727. #endif
  728.     return (lalloc((long_u)size, TRUE));
  729. }
  730.  
  731. /*
  732.  * Allocate memory like lalloc() and set all bytes to zero.
  733.  */
  734.     char_u *
  735. lalloc_clear(size, message)
  736.     long_u    size;
  737.     int        message;
  738. {
  739.     char_u *p;
  740.  
  741.     p = (lalloc(size, message));
  742.     if (p != NULL)
  743.     (void)vim_memset(p, 0, (size_t)size);
  744.     return p;
  745. }
  746.  
  747. /*
  748.  * Low level memory allocation function.
  749.  * This is used often, KEEP IT FAST!
  750.  */
  751.     char_u *
  752. lalloc(size, message)
  753.     long_u    size;
  754.     int        message;
  755. {
  756.     char_u    *p;            /* pointer to new storage space */
  757.     static int    releasing = FALSE;  /* don't do mf_release_all() recursive */
  758.     int        try_again;
  759. #if defined(HAVE_AVAIL_MEM) && !defined(SMALL_MEM)
  760.     static long_u allocated = 0;    /* allocated since last avail check */
  761. #endif
  762.  
  763.     /* Safety check for allocating zero bytes */
  764.     if (size == 0)
  765.     {
  766.     /* Don't hide this message */
  767.     emsg_silent = 0;
  768.     EMSGN(_("E341: Internal error: lalloc(%ld, )"), size);
  769.     return NULL;
  770.     }
  771.  
  772. #ifdef MEM_PROFILE
  773.     mem_pre_alloc_l(&size);
  774. #endif
  775.  
  776. #if defined(MSDOS) && !defined(DJGPP)
  777.     if (size >= 0xfff0)        /* in MSDOS we can't deal with >64K blocks */
  778.     p = NULL;
  779.     else
  780. #endif
  781.  
  782.     /*
  783.      * Loop when out of memory: Try to release some memfile blocks and
  784.      * if some blocks are released call malloc again.
  785.      */
  786.     for (;;)
  787.     {
  788.     /*
  789.      * Handle three kind of systems:
  790.      * 1. No check for available memory: Just return.
  791.      * 2. Slow check for available memory: call mch_avail_mem() after
  792.      *    allocating KEEP_ROOM amount of memory.
  793.      * 3. Strict check for available memory: call mch_avail_mem()
  794.      */
  795.     if ((p = (char_u *)malloc((size_t)size)) != NULL)
  796.     {
  797. #ifndef HAVE_AVAIL_MEM
  798.         /* 1. No check for available memory: Just return. */
  799.         goto theend;
  800. #else
  801. # ifndef SMALL_MEM
  802.         /* 2. Slow check for available memory: call mch_avail_mem() after
  803.          *    allocating (KEEP_ROOM / 2) amount of memory. */
  804.         allocated += size;
  805.         if (allocated < KEEP_ROOM / 2)
  806.         goto theend;
  807.         allocated = 0;
  808. # endif
  809.         /* 3. check for available memory: call mch_avail_mem() */
  810.         if (mch_avail_mem(TRUE) < KEEP_ROOM && !releasing)
  811.         {
  812.         vim_free((char *)p);    /* System is low... no go! */
  813.         p = NULL;
  814.         }
  815.         else
  816.         goto theend;
  817. #endif
  818.     }
  819.     /*
  820.      * Remember that mf_release_all() is being called to avoid an endless
  821.      * loop, because mf_release_all() may call alloc() recursively.
  822.      */
  823.     if (releasing)
  824.         break;
  825.     releasing = TRUE;
  826.     try_again = mf_release_all();
  827.     releasing = FALSE;
  828.     if (!try_again)
  829.         break;
  830.     }
  831.  
  832.     if (message && p == NULL)
  833.     do_outofmem_msg(size);
  834.  
  835. theend:
  836. #ifdef MEM_PROFILE
  837.     mem_post_alloc((void **)&p, (size_t)size);
  838. #endif
  839.     return p;
  840. }
  841.  
  842. #if defined(MEM_PROFILE) || defined(PROTO)
  843. /*
  844.  * realloc() with memory profiling.
  845.  */
  846.     void *
  847. mem_realloc(ptr, size)
  848.     void *ptr;
  849.     size_t size;
  850. {
  851.     void *p;
  852.  
  853.     mem_pre_free(&ptr);
  854.     mem_pre_alloc_s(&size);
  855.  
  856.     p = realloc(ptr, size);
  857.  
  858.     mem_post_alloc(&p, size);
  859.  
  860.     return p;
  861. }
  862. #endif
  863.  
  864. /*
  865. * Avoid repeating the error message many times (they take 1 second each).
  866. * Did_outofmem_msg is reset when a character is read.
  867. */
  868.     void
  869. do_outofmem_msg(size)
  870.     long_u    size;
  871. {
  872.     if (!did_outofmem_msg)
  873.     {
  874.     /* Don't hide this message */
  875.     emsg_silent = 0;
  876.     EMSG2(_("E342: Out of memory!  (allocating %lu bytes)"), size);
  877.     did_outofmem_msg = TRUE;
  878.     }
  879. }
  880.  
  881. /*
  882.  * copy a string into newly allocated memory
  883.  */
  884.     char_u *
  885. vim_strsave(string)
  886.     char_u    *string;
  887. {
  888.     char_u    *p;
  889.     unsigned    len;
  890.  
  891.     len = (unsigned)STRLEN(string) + 1;
  892.     p = alloc(len);
  893.     if (p != NULL)
  894.     mch_memmove(p, string, (size_t)len);
  895.     return p;
  896. }
  897.  
  898.     char_u *
  899. vim_strnsave(string, len)
  900.     char_u    *string;
  901.     int        len;
  902. {
  903.     char_u    *p;
  904.  
  905.     p = alloc((unsigned)(len + 1));
  906.     if (p != NULL)
  907.     {
  908.     STRNCPY(p, string, len);
  909.     p[len] = NUL;
  910.     }
  911.     return p;
  912. }
  913.  
  914. #if 0    /* not used */
  915. /*
  916.  * like vim_strnsave(), but remove backslashes from the string.
  917.  */
  918.     char_u *
  919. vim_strnsave_esc(string, len)
  920.     char_u    *string;
  921.     int        len;
  922. {
  923.     char_u *p1, *p2;
  924.  
  925.     p1 = alloc((unsigned) (len + 1));
  926.     if (p1 != NULL)
  927.     {
  928.     STRNCPY(p1, string, len);
  929.     p1[len] = NUL;
  930.     for (p2 = p1; *p2; ++p2)
  931.         if (*p2 == '\\' && *(p2 + 1) != NUL)
  932.         STRCPY(p2, p2 + 1);
  933.     }
  934.     return p1;
  935. }
  936. #endif
  937.  
  938. /*
  939.  * Same as vim_strsave(), but any characters found in esc_chars are preceded
  940.  * by a backslash.
  941.  */
  942.     char_u *
  943. vim_strsave_escaped(string, esc_chars)
  944.     char_u    *string;
  945.     char_u    *esc_chars;
  946. {
  947.     char_u    *p;
  948.     char_u    *p2;
  949.     char_u    *escaped_string;
  950.     unsigned    length;
  951. #ifdef FEAT_MBYTE
  952.     int        l;
  953. #endif
  954.  
  955.     /*
  956.      * First count the number of backslashes required.
  957.      * Then allocate the memory and insert them.
  958.      */
  959.     length = 1;                /* count the trailing NUL */
  960.     for (p = string; *p; p++)
  961.     {
  962. #ifdef FEAT_MBYTE
  963.     if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
  964.     {
  965.         length += l;        /* count a multibyte char */
  966.         p += l - 1;
  967.         continue;
  968.     }
  969. #endif
  970.     if (vim_strchr(esc_chars, *p) != NULL)
  971.         ++length;            /* count a backslash */
  972.     ++length;            /* count an ordinary char */
  973.     }
  974.     escaped_string = alloc(length);
  975.     if (escaped_string != NULL)
  976.     {
  977.     p2 = escaped_string;
  978.     for (p = string; *p; p++)
  979.     {
  980. #ifdef FEAT_MBYTE
  981.         if (has_mbyte && (l = (*mb_ptr2len_check)(p)) > 1)
  982.         {
  983.         mch_memmove(p2, p, (size_t)l);
  984.         p2 += l;
  985.         p += l - 1;        /* skip multibyte char  */
  986.         continue;
  987.         }
  988. #endif
  989.         if (vim_strchr(esc_chars, *p) != NULL)
  990.         *p2++ = '\\';
  991.         *p2++ = *p;
  992.     }
  993.     *p2 = NUL;
  994.     }
  995.     return escaped_string;
  996. }
  997.  
  998. /*
  999.  * Like vim_strsave(), but make all characters uppercase.
  1000.  * This uses ASCII lower-to-upper case translation, language independent.
  1001.  */
  1002.     char_u *
  1003. vim_strsave_up(string)
  1004.     char_u    *string;
  1005. {
  1006.     char_u *p1;
  1007.  
  1008.     p1 = vim_strsave(string);
  1009.     vim_strup(p1);
  1010.     return p1;
  1011. }
  1012.  
  1013. /*
  1014.  * Like vim_strnsave(), but make all characters uppercase.
  1015.  * This uses ASCII lower-to-upper case translation, language independent.
  1016.  */
  1017.     char_u *
  1018. vim_strnsave_up(string, len)
  1019.     char_u    *string;
  1020.     int        len;
  1021. {
  1022.     char_u *p1;
  1023.  
  1024.     p1 = vim_strnsave(string, len);
  1025.     vim_strup(p1);
  1026.     return p1;
  1027. }
  1028.  
  1029. /*
  1030.  * ASCII lower-to-upper case translation, language independent.
  1031.  */
  1032.     void
  1033. vim_strup(p)
  1034.     char_u    *p;
  1035. {
  1036.     char_u  *p2;
  1037.     int        c;
  1038.  
  1039.     if (p != NULL)
  1040.     {
  1041.     p2 = p;
  1042.     while ((c = *p2) != NUL)
  1043. #ifdef EBCDIC
  1044.         *p2++ = isalpha(c) ? toupper(c) : c;
  1045. #else
  1046.         *p2++ = (c < 'a' || c > 'z') ? c : (c - 0x20);
  1047. #endif
  1048.     }
  1049. }
  1050.  
  1051. /*
  1052.  * copy a space a number of times
  1053.  */
  1054.     void
  1055. copy_spaces(ptr, count)
  1056.     char_u    *ptr;
  1057.     size_t    count;
  1058. {
  1059.     size_t    i = count;
  1060.     char_u    *p = ptr;
  1061.  
  1062.     while (i--)
  1063.     *p++ = ' ';
  1064. }
  1065.  
  1066. #if defined(FEAT_VISUALEXTRA) || defined(PROTO)
  1067. /*
  1068.  * copy a character a number of times
  1069.  */
  1070.     void
  1071. copy_chars(ptr, count, c)
  1072.     char_u    *ptr;
  1073.     size_t    count;
  1074.     int        c;
  1075. {
  1076.     size_t    i = count;
  1077.     char_u    *p = ptr;
  1078.  
  1079.     while (i--)
  1080.     *p++ = c;
  1081. }
  1082. #endif
  1083.  
  1084. /*
  1085.  * delete spaces at the end of a string
  1086.  */
  1087.     void
  1088. del_trailing_spaces(ptr)
  1089.     char_u    *ptr;
  1090. {
  1091.     char_u    *q;
  1092.  
  1093.     q = ptr + STRLEN(ptr);
  1094.     while (--q > ptr && vim_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V)
  1095.     *q = NUL;
  1096. }
  1097.  
  1098. /*
  1099.  * vim_strncpy()
  1100.  *
  1101.  * This is here because strncpy() does not guarantee successful results when
  1102.  * the to and from strings overlap.  It is only currently called from nextwild()
  1103.  * which copies part of the command line to another part of the command line.
  1104.  * This produced garbage when expanding files etc in the middle of the command
  1105.  * line (on my terminal, anyway) -- webb.
  1106.  */
  1107.     void
  1108. vim_strncpy(to, from, len)
  1109.     char_u *to;
  1110.     char_u *from;
  1111.     int len;
  1112. {
  1113.     int i;
  1114.  
  1115.     if (to <= from)
  1116.     {
  1117.     while (len-- && *from)
  1118.         *to++ = *from++;
  1119.     if (len >= 0)
  1120.         *to = *from;    /* Copy NUL */
  1121.     }
  1122.     else
  1123.     {
  1124.     for (i = 0; i < len; i++)
  1125.     {
  1126.         to++;
  1127.         if (*from++ == NUL)
  1128.         {
  1129.         i++;
  1130.         break;
  1131.         }
  1132.     }
  1133.     for (; i > 0; i--)
  1134.         *--to = *--from;
  1135.     }
  1136. }
  1137.  
  1138. /*
  1139.  * Isolate one part of a string option where parts are separated with
  1140.  * "sep_chars".
  1141.  * The part is copied into buf[maxlen].
  1142.  * "*option" is advanced to the next part.
  1143.  * The length is returned.
  1144.  */
  1145.     int
  1146. copy_option_part(option, buf, maxlen, sep_chars)
  1147.     char_u    **option;
  1148.     char_u    *buf;
  1149.     int        maxlen;
  1150.     char    *sep_chars;
  1151. {
  1152.     int        len = 0;
  1153.     char_u  *p = *option;
  1154.  
  1155.     /* skip '.' at start of option part, for 'suffixes' */
  1156.     if (*p == '.')
  1157.     buf[len++] = *p++;
  1158.     while (*p != NUL && vim_strchr((char_u *)sep_chars, *p) == NULL)
  1159.     {
  1160.     /*
  1161.      * Skip backslash before a separator character and space.
  1162.      */
  1163.     if (p[0] == '\\' && vim_strchr((char_u *)sep_chars, p[1]) != NULL)
  1164.         ++p;
  1165.     if (len < maxlen - 1)
  1166.         buf[len++] = *p;
  1167.     ++p;
  1168.     }
  1169.     buf[len] = NUL;
  1170.  
  1171.     if (*p != NUL && *p != ',')    /* skip non-standard separator */
  1172.     ++p;
  1173.     p = skip_to_option_part(p);    /* p points to next file name */
  1174.  
  1175.     *option = p;
  1176.     return len;
  1177. }
  1178.  
  1179. /*
  1180.  * replacement for free() that ignores NULL pointers
  1181.  */
  1182.     void
  1183. vim_free(x)
  1184.     void *x;
  1185. {
  1186.     if (x != NULL)
  1187.     {
  1188. #ifdef MEM_PROFILE
  1189.     mem_pre_free(&x);
  1190. #endif
  1191.     free(x);
  1192.     }
  1193. }
  1194.  
  1195. #ifndef HAVE_MEMSET
  1196.     void *
  1197. vim_memset(ptr, c, size)
  1198.     void    *ptr;
  1199.     int        c;
  1200.     size_t  size;
  1201. {
  1202.     char *p = ptr;
  1203.  
  1204.     while (size-- > 0)
  1205.     *p++ = c;
  1206.     return ptr;
  1207. }
  1208. #endif
  1209.  
  1210. #ifdef VIM_MEMCMP
  1211. /*
  1212.  * Return zero when "b1" and "b2" are the same for "len" bytes.
  1213.  * Return non-zero otherwise.
  1214.  */
  1215.     int
  1216. vim_memcmp(b1, b2, len)
  1217.     void    *b1;
  1218.     void    *b2;
  1219.     size_t  len;
  1220. {
  1221.     char_u  *p1 = (char_u *)b1, *p2 = (char_u *)b2;
  1222.  
  1223.     for ( ; len > 0; --len)
  1224.     {
  1225.     if (*p1 != *p2)
  1226.         return 1;
  1227.     ++p1;
  1228.     ++p2;
  1229.     }
  1230.     return 0;
  1231. }
  1232. #endif
  1233.  
  1234. #ifdef VIM_MEMMOVE
  1235. /*
  1236.  * Version of memmove() that handles overlapping source and destination.
  1237.  * For systems that don't have a function that is guaranteed to do that (SYSV).
  1238.  */
  1239.     void
  1240. mch_memmove(dst_arg, src_arg, len)
  1241.     void    *src_arg, *dst_arg;
  1242.     size_t  len;
  1243. {
  1244.     /*
  1245.      * A void doesn't have a size, we use char pointers.
  1246.      */
  1247.     char *dst = dst_arg, *src = src_arg;
  1248.  
  1249.                     /* overlap, copy backwards */
  1250.     if (dst > src && dst < src + len)
  1251.     {
  1252.     src += len;
  1253.     dst += len;
  1254.     while (len-- > 0)
  1255.         *--dst = *--src;
  1256.     }
  1257.     else                /* copy forwards */
  1258.     while (len-- > 0)
  1259.         *dst++ = *src++;
  1260. }
  1261. #endif
  1262.  
  1263. #if (!defined(HAVE_STRCASECMP) && !defined(HAVE_STRICMP)) || defined(PROTO)
  1264. /*
  1265.  * Compare two strings, ignoring case.
  1266.  * return 0 for match, < 0 for smaller, > 0 for bigger
  1267.  */
  1268.     int
  1269. vim_stricmp(s1, s2)
  1270.     char    *s1;
  1271.     char    *s2;
  1272. {
  1273.     int        i;
  1274.  
  1275.     for (;;)
  1276.     {
  1277.     i = (int)TO_LOWER(*s1) - (int)TO_LOWER(*s2);
  1278.     if (i != 0)
  1279.         return i;                /* this character different */
  1280.     if (*s1 == NUL)
  1281.         break;                /* strings match until NUL */
  1282.     ++s1;
  1283.     ++s2;
  1284.     }
  1285.     return 0;                    /* strings match */
  1286. }
  1287. #endif
  1288.  
  1289. #if (!defined(HAVE_STRNCASECMP) && !defined(HAVE_STRNICMP)) || defined(PROTO)
  1290. /*
  1291.  * Compare two strings, for length "len", ignoring case.
  1292.  * return 0 for match, < 0 for smaller, > 0 for bigger
  1293.  */
  1294.     int
  1295. vim_strnicmp(s1, s2, len)
  1296.     char    *s1;
  1297.     char    *s2;
  1298.     size_t    len;
  1299. {
  1300.     int        i;
  1301.  
  1302.     while (len > 0)
  1303.     {
  1304.     i = (int)TO_LOWER(*s1) - (int)TO_LOWER(*s2);
  1305.     if (i != 0)
  1306.         return i;                /* this character different */
  1307.     if (*s1 == NUL)
  1308.         break;                /* strings match until NUL */
  1309.     ++s1;
  1310.     ++s2;
  1311.     --len;
  1312.     }
  1313.     return 0;                    /* strings match */
  1314. }
  1315. #endif
  1316.  
  1317. #if 0    /* currently not used */
  1318. /*
  1319.  * Check if string "s2" appears somewhere in "s1" while ignoring case.
  1320.  * Return NULL if not, a pointer to the first occurrence if it does.
  1321.  */
  1322.     char_u *
  1323. vim_stristr(s1, s2)
  1324.     char_u    *s1;
  1325.     char_u    *s2;
  1326. {
  1327.     char_u    *p;
  1328.     int        len = STRLEN(s2);
  1329.     char_u    *end = s1 + STRLEN(s1) - len;
  1330.  
  1331.     for (p = s1; p <= end; ++p)
  1332.     if (STRNICMP(p, s2, len) == 0)
  1333.         return p;
  1334.     return NULL;
  1335. }
  1336. #endif
  1337.  
  1338. /*
  1339.  * Version of strchr() and strrchr() that handle unsigned char strings
  1340.  * with characters above 128 correctly. Also it doesn't return a pointer to
  1341.  * the NUL at the end of the string.
  1342.  */
  1343.     char_u  *
  1344. vim_strchr(string, c)
  1345.     char_u    *string;
  1346.     int        c;
  1347. {
  1348.     char_u    *p;
  1349.     int        b;
  1350.  
  1351.     p = string;
  1352. #ifdef FEAT_MBYTE
  1353.     if (enc_utf8 && c >= 0x80)
  1354.     {
  1355.     while (*p != NUL)
  1356.     {
  1357.         if (utf_ptr2char(p) == c)
  1358.         return p;
  1359.         p += (*mb_ptr2len_check)(p);
  1360.     }
  1361.     return NULL;
  1362.     }
  1363.     if (enc_dbcs != 0 && c > 255)
  1364.     {
  1365.     int    n2 = c & 0xff;
  1366.  
  1367.     c = ((unsigned)c >> 8) & 0xff;
  1368.     while ((b = *p) != NUL)
  1369.     {
  1370.         if (b == c && p[1] == n2)
  1371.         return p;
  1372.         p += (*mb_ptr2len_check)(p);
  1373.     }
  1374.     return NULL;
  1375.     }
  1376.     if (has_mbyte)
  1377.     {
  1378.     while ((b = *p) != NUL)
  1379.     {
  1380.         if (b == c)
  1381.         return p;
  1382.         p += (*mb_ptr2len_check)(p);
  1383.     }
  1384.     return NULL;
  1385.     }
  1386. #endif
  1387.     while ((b = *p) != NUL)
  1388.     {
  1389.     if (b == c)
  1390.         return p;
  1391.     ++p;
  1392.     }
  1393.     return NULL;
  1394. }
  1395.  
  1396. /*
  1397.  * Search for last occurrence of "c" in "string".
  1398.  * return NULL if not found.
  1399.  * Does not handle multi-byte!
  1400.  */
  1401.     char_u  *
  1402. vim_strrchr(string, c)
  1403.     char_u    *string;
  1404.     int        c;
  1405. {
  1406.     char_u    *retval = NULL;
  1407.  
  1408.     while (*string)
  1409.     {
  1410.     if (*string == c)
  1411.         retval = string;
  1412. #ifdef FEAT_MBYTE
  1413.     if (has_mbyte)
  1414.         string += (*mb_ptr2len_check)(string);
  1415.     else
  1416. #endif
  1417.         ++string;
  1418.     }
  1419.     return retval;
  1420. }
  1421.  
  1422. /*
  1423.  * Vim's version of strpbrk(), in case it's missing.
  1424.  * Don't generate a prototype for this, causes problems when it's not used.
  1425.  */
  1426. #ifndef PROTO
  1427. # ifndef HAVE_STRPBRK
  1428. #  ifdef vim_strpbrk
  1429. #   undef vim_strpbrk
  1430. #  endif
  1431.     char_u *
  1432. vim_strpbrk(s, charset)
  1433.     char_u    *s;
  1434.     char_u    *charset;
  1435. {
  1436.     while (*s)
  1437.     {
  1438.     if (vim_strchr(charset, *s) != NULL)
  1439.         return s;
  1440. #ifdef FEAT_MBYTE
  1441.     if (has_mbyte)
  1442.         s += (*mb_ptr2len_check)(s);
  1443.     else
  1444. #endif
  1445.         ++s;
  1446.     }
  1447.     return NULL;
  1448. }
  1449. # endif
  1450. #endif
  1451.  
  1452. /*
  1453.  * Vim has its own isspace() function, because on some machines isspace()
  1454.  * can't handle characters above 128.
  1455.  */
  1456.     int
  1457. vim_isspace(x)
  1458.     int        x;
  1459. {
  1460.     return ((x >= 9 && x <= 13) || x == ' ');
  1461. }
  1462.  
  1463. /************************************************************************
  1464.  * Functions for hanlding growing arrays.
  1465.  */
  1466.  
  1467. /*
  1468.  * Clear an allocated growing array.
  1469.  */
  1470.     void
  1471. ga_clear(gap)
  1472.     garray_T *gap;
  1473. {
  1474.     vim_free(gap->ga_data);
  1475.     ga_init(gap);
  1476. }
  1477.  
  1478. #if defined(FEAT_EVAL) || defined(PROTO)
  1479. /*
  1480.  * Clear a growing array that contains a list of strings.
  1481.  */
  1482.     void
  1483. ga_clear_strings(gap)
  1484.     garray_T *gap;
  1485. {
  1486.     int        i;
  1487.  
  1488.     for (i = 0; i < gap->ga_len; ++i)
  1489.     vim_free(((char_u **)(gap->ga_data))[i]);
  1490.     ga_clear(gap);
  1491. }
  1492. #endif
  1493.  
  1494. /*
  1495.  * Initialize a growing array.    Don't forget to set ga_itemsize and
  1496.  * ga_growsize!  Or use ga_init2().
  1497.  */
  1498.     void
  1499. ga_init(gap)
  1500.     garray_T *gap;
  1501. {
  1502.     gap->ga_data = NULL;
  1503.     gap->ga_room = 0;
  1504.     gap->ga_len = 0;
  1505. }
  1506.  
  1507.     void
  1508. ga_init2(gap, itemsize, growsize)
  1509.     garray_T    *gap;
  1510.     int        itemsize;
  1511.     int        growsize;
  1512. {
  1513.     ga_init(gap);
  1514.     gap->ga_itemsize = itemsize;
  1515.     gap->ga_growsize = growsize;
  1516. }
  1517.  
  1518. /*
  1519.  * Make room in growing array "gap" for at least "n" items.
  1520.  * Return FAIL for failure, OK otherwise.
  1521.  */
  1522.     int
  1523. ga_grow(gap, n)
  1524.     garray_T    *gap;
  1525.     int        n;
  1526. {
  1527.     size_t    len;
  1528.     char_u    *pp;
  1529.  
  1530.     if (gap->ga_room < n)
  1531.     {
  1532.     if (n < gap->ga_growsize)
  1533.         n = gap->ga_growsize;
  1534.     len = gap->ga_itemsize * (gap->ga_len + n);
  1535.     pp = alloc_clear((unsigned)len);
  1536.     if (pp == NULL)
  1537.         return FAIL;
  1538.     gap->ga_room = n;
  1539.     if (gap->ga_data != NULL)
  1540.     {
  1541.         mch_memmove(pp, gap->ga_data,
  1542.                       (size_t)(gap->ga_itemsize * gap->ga_len));
  1543.         vim_free(gap->ga_data);
  1544.     }
  1545.     gap->ga_data = pp;
  1546.     }
  1547.     return OK;
  1548. }
  1549.  
  1550. #if defined(FEAT_EVAL) || defined(FEAT_CMDL_COMPL) || defined(FEAT_PYTHON) \
  1551.     || defined(FEAT_RUBY) || defined(FEAT_TCL) || defined(FEAT_PERL) \
  1552.     || defined(FEAT_GUI_GTK) || defined(FEAT_GUI_MOTIF) || defined(PROTO)
  1553. /*
  1554.  * Concatenate a string to a growarray which contains characters.
  1555.  * Note: Does NOT copy the NUL at the end!
  1556.  */
  1557.     void
  1558. ga_concat(gap, s)
  1559.     garray_T    *gap;
  1560.     char_u    *s;
  1561. {
  1562.     int    len = (int)STRLEN(s);
  1563.  
  1564.     if (ga_grow(gap, len) == OK)
  1565.     {
  1566.     mch_memmove((char *)gap->ga_data + gap->ga_len, s, (size_t)len);
  1567.     gap->ga_len += len;
  1568.     gap->ga_room -= len;
  1569.     }
  1570. }
  1571.  
  1572. /*
  1573.  * Append one byte to a growarray which contains bytes.
  1574.  */
  1575.     void
  1576. ga_append(gap, c)
  1577.     garray_T    *gap;
  1578.     int        c;
  1579. {
  1580.     if (ga_grow(gap, 1) == OK)
  1581.     {
  1582.     *((char *)gap->ga_data + gap->ga_len) = c;
  1583.     ++gap->ga_len;
  1584.     --gap->ga_room;
  1585.     }
  1586. }
  1587. #endif
  1588.  
  1589. /************************************************************************
  1590.  * functions that use lookup tables for various things, generally to do with
  1591.  * special key codes.
  1592.  */
  1593.  
  1594. /*
  1595.  * Some useful tables.
  1596.  */
  1597.  
  1598. static struct modmasktable
  1599. {
  1600.     short    mod_mask;    /* Bit-mask for particular key modifier */
  1601.     short    mod_flag;    /* Bit(s) for particular key modifier */
  1602.     char_u    name;        /* Single letter name of modifier */
  1603. } mod_mask_table[] =
  1604. {
  1605.     {MOD_MASK_ALT,        MOD_MASK_ALT,        (char_u)'M'},
  1606.     {MOD_MASK_CTRL,        MOD_MASK_CTRL,        (char_u)'C'},
  1607.     {MOD_MASK_SHIFT,        MOD_MASK_SHIFT,        (char_u)'S'},
  1608.     {MOD_MASK_MULTI_CLICK,    MOD_MASK_2CLICK,    (char_u)'2'},
  1609.     {MOD_MASK_MULTI_CLICK,    MOD_MASK_3CLICK,    (char_u)'3'},
  1610.     {MOD_MASK_MULTI_CLICK,    MOD_MASK_4CLICK,    (char_u)'4'},
  1611. #ifdef MACOS
  1612.     {MOD_MASK_CMD,        MOD_MASK_CMD,        (char_u)'D'},
  1613. #endif
  1614.     /* 'A' must be the last one */
  1615.     {MOD_MASK_ALT,        MOD_MASK_ALT,        (char_u)'A'},
  1616.     {0, 0, NUL}
  1617. };
  1618.  
  1619. /*
  1620.  * Shifted key terminal codes and their unshifted equivalent.
  1621.  * Don't add mouse codes here, they are handled seperately!
  1622.  */
  1623. #define MOD_KEYS_ENTRY_SIZE 5
  1624.  
  1625. static char_u modifier_keys_table[] =
  1626. {
  1627. /*  mod mask        with modifier        without modifier */
  1628.     MOD_MASK_SHIFT, '&', '9',            '@', '1',    /* begin */
  1629.     MOD_MASK_SHIFT, '&', '0',            '@', '2',    /* cancel */
  1630.     MOD_MASK_SHIFT, '*', '1',            '@', '4',    /* command */
  1631.     MOD_MASK_SHIFT, '*', '2',            '@', '5',    /* copy */
  1632.     MOD_MASK_SHIFT, '*', '3',            '@', '6',    /* create */
  1633.     MOD_MASK_SHIFT, '*', '4',            'k', 'D',    /* delete char */
  1634.     MOD_MASK_SHIFT, '*', '5',            'k', 'L',    /* delete line */
  1635.     MOD_MASK_SHIFT, '*', '7',            '@', '7',    /* end */
  1636.     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_END,    '@', '7',    /* end */
  1637.     MOD_MASK_SHIFT, '*', '9',            '@', '9',    /* exit */
  1638.     MOD_MASK_SHIFT, '*', '0',            '@', '0',    /* find */
  1639.     MOD_MASK_SHIFT, '#', '1',            '%', '1',    /* help */
  1640.     MOD_MASK_SHIFT, '#', '2',            'k', 'h',    /* home */
  1641.     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_HOME,    'k', 'h',    /* home */
  1642.     MOD_MASK_SHIFT, '#', '3',            'k', 'I',    /* insert */
  1643.     MOD_MASK_SHIFT, '#', '4',            'k', 'l',    /* left arrow */
  1644.     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_LEFT,    'k', 'l',    /* left arrow */
  1645.     MOD_MASK_SHIFT, '%', 'a',            '%', '3',    /* message */
  1646.     MOD_MASK_SHIFT, '%', 'b',            '%', '4',    /* move */
  1647.     MOD_MASK_SHIFT, '%', 'c',            '%', '5',    /* next */
  1648.     MOD_MASK_SHIFT, '%', 'd',            '%', '7',    /* options */
  1649.     MOD_MASK_SHIFT, '%', 'e',            '%', '8',    /* previous */
  1650.     MOD_MASK_SHIFT, '%', 'f',            '%', '9',    /* print */
  1651.     MOD_MASK_SHIFT, '%', 'g',            '%', '0',    /* redo */
  1652.     MOD_MASK_SHIFT, '%', 'h',            '&', '3',    /* replace */
  1653.     MOD_MASK_SHIFT, '%', 'i',            'k', 'r',    /* right arr. */
  1654.     MOD_MASK_CTRL,  KS_EXTRA, (int)KE_C_RIGHT,    'k', 'r',    /* right arr. */
  1655.     MOD_MASK_SHIFT, '%', 'j',            '&', '5',    /* resume */
  1656.     MOD_MASK_SHIFT, '!', '1',            '&', '6',    /* save */
  1657.     MOD_MASK_SHIFT, '!', '2',            '&', '7',    /* suspend */
  1658.     MOD_MASK_SHIFT, '!', '3',            '&', '8',    /* undo */
  1659.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_UP,    'k', 'u',    /* up arrow */
  1660.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_DOWN,    'k', 'd',    /* down arrow */
  1661.  
  1662.                                 /* vt100 F1 */
  1663.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF1,    KS_EXTRA, (int)KE_XF1,
  1664.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF2,    KS_EXTRA, (int)KE_XF2,
  1665.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF3,    KS_EXTRA, (int)KE_XF3,
  1666.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_XF4,    KS_EXTRA, (int)KE_XF4,
  1667.  
  1668.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F1,    'k', '1',    /* F1 */
  1669.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F2,    'k', '2',
  1670.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F3,    'k', '3',
  1671.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F4,    'k', '4',
  1672.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F5,    'k', '5',
  1673.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F6,    'k', '6',
  1674.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F7,    'k', '7',
  1675.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F8,    'k', '8',
  1676.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F9,    'k', '9',
  1677.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F10,    'k', ';',    /* F10 */
  1678.  
  1679.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F11,    'F', '1',
  1680.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F12,    'F', '2',
  1681.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F13,    'F', '3',
  1682.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F14,    'F', '4',
  1683.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F15,    'F', '5',
  1684.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F16,    'F', '6',
  1685.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F17,    'F', '7',
  1686.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F18,    'F', '8',
  1687.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F19,    'F', '9',
  1688.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F20,    'F', 'A',
  1689.  
  1690.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F21,    'F', 'B',
  1691.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F22,    'F', 'C',
  1692.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F23,    'F', 'D',
  1693.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F24,    'F', 'E',
  1694.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F25,    'F', 'F',
  1695.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F26,    'F', 'G',
  1696.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F27,    'F', 'H',
  1697.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F28,    'F', 'I',
  1698.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F29,    'F', 'J',
  1699.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F30,    'F', 'K',
  1700.  
  1701.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F31,    'F', 'L',
  1702.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F32,    'F', 'M',
  1703.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F33,    'F', 'N',
  1704.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F34,    'F', 'O',
  1705.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F35,    'F', 'P',
  1706.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F36,    'F', 'Q',
  1707.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_F37,    'F', 'R',
  1708.  
  1709.                                 /* TAB pseudo code*/
  1710.     MOD_MASK_SHIFT, KS_EXTRA, (int)KE_S_TAB,    KS_EXTRA, (int)KE_TAB,
  1711.  
  1712.     NUL
  1713. };
  1714.  
  1715. static struct key_name_entry
  1716. {
  1717.     int        key;    /* Special key code or ascii value */
  1718.     char_u  *name;    /* Name of key */
  1719. } key_names_table[] =
  1720. {
  1721.     {' ',        (char_u *)"Space"},
  1722.     {TAB,        (char_u *)"Tab"},
  1723.     {K_TAB,        (char_u *)"Tab"},
  1724.     {NL,        (char_u *)"NL"},
  1725.     {NL,        (char_u *)"NewLine"},    /* Alternative name */
  1726.     {NL,        (char_u *)"LineFeed"},    /* Alternative name */
  1727.     {NL,        (char_u *)"LF"},    /* Alternative name */
  1728.     {CR,        (char_u *)"CR"},
  1729.     {CR,        (char_u *)"Return"},    /* Alternative name */
  1730.     {CR,        (char_u *)"Enter"},    /* Alternative name */
  1731.     {K_BS,        (char_u *)"BS"},
  1732.     {K_BS,        (char_u *)"BackSpace"},    /* Alternative name */
  1733.     {ESC,        (char_u *)"Esc"},
  1734.     {CSI,        (char_u *)"CSI"},
  1735.     {K_CSI,        (char_u *)"xCSI"},
  1736.     {'|',        (char_u *)"Bar"},
  1737.     {'\\',        (char_u *)"Bslash"},
  1738.     {K_DEL,        (char_u *)"Del"},
  1739.     {K_DEL,        (char_u *)"Delete"},    /* Alternative name */
  1740.     {K_KDEL,        (char_u *)"kDel"},
  1741.     {K_UP,        (char_u *)"Up"},
  1742.     {K_DOWN,        (char_u *)"Down"},
  1743.     {K_LEFT,        (char_u *)"Left"},
  1744.     {K_RIGHT,        (char_u *)"Right"},
  1745.  
  1746.     {K_F1,        (char_u *)"F1"},
  1747.     {K_F2,        (char_u *)"F2"},
  1748.     {K_F3,        (char_u *)"F3"},
  1749.     {K_F4,        (char_u *)"F4"},
  1750.     {K_F5,        (char_u *)"F5"},
  1751.     {K_F6,        (char_u *)"F6"},
  1752.     {K_F7,        (char_u *)"F7"},
  1753.     {K_F8,        (char_u *)"F8"},
  1754.     {K_F9,        (char_u *)"F9"},
  1755.     {K_F10,        (char_u *)"F10"},
  1756.  
  1757.     {K_F11,        (char_u *)"F11"},
  1758.     {K_F12,        (char_u *)"F12"},
  1759.     {K_F13,        (char_u *)"F13"},
  1760.     {K_F14,        (char_u *)"F14"},
  1761.     {K_F15,        (char_u *)"F15"},
  1762.     {K_F16,        (char_u *)"F16"},
  1763.     {K_F17,        (char_u *)"F17"},
  1764.     {K_F18,        (char_u *)"F18"},
  1765.     {K_F19,        (char_u *)"F19"},
  1766.     {K_F20,        (char_u *)"F20"},
  1767.  
  1768.     {K_F21,        (char_u *)"F21"},
  1769.     {K_F22,        (char_u *)"F22"},
  1770.     {K_F23,        (char_u *)"F23"},
  1771.     {K_F24,        (char_u *)"F24"},
  1772.     {K_F25,        (char_u *)"F25"},
  1773.     {K_F26,        (char_u *)"F26"},
  1774.     {K_F27,        (char_u *)"F27"},
  1775.     {K_F28,        (char_u *)"F28"},
  1776.     {K_F29,        (char_u *)"F29"},
  1777.     {K_F30,        (char_u *)"F30"},
  1778.  
  1779.     {K_F31,        (char_u *)"F31"},
  1780.     {K_F32,        (char_u *)"F32"},
  1781.     {K_F33,        (char_u *)"F33"},
  1782.     {K_F34,        (char_u *)"F34"},
  1783.     {K_F35,        (char_u *)"F35"},
  1784.     {K_F36,        (char_u *)"F36"},
  1785.     {K_F37,        (char_u *)"F37"},
  1786.  
  1787.     {K_XF1,        (char_u *)"xF1"},
  1788.     {K_XF2,        (char_u *)"xF2"},
  1789.     {K_XF3,        (char_u *)"xF3"},
  1790.     {K_XF4,        (char_u *)"xF4"},
  1791.  
  1792.     {K_HELP,        (char_u *)"Help"},
  1793.     {K_UNDO,        (char_u *)"Undo"},
  1794.     {K_INS,        (char_u *)"Insert"},
  1795.     {K_INS,        (char_u *)"Ins"},    /* Alternative name */
  1796.     {K_KINS,        (char_u *)"kInsert"},
  1797.     {K_HOME,        (char_u *)"Home"},
  1798.     {K_KHOME,        (char_u *)"kHome"},
  1799.     {K_XHOME,        (char_u *)"xHome"},
  1800.     {K_END,        (char_u *)"End"},
  1801.     {K_KEND,        (char_u *)"kEnd"},
  1802.     {K_XEND,        (char_u *)"xEnd"},
  1803.     {K_PAGEUP,        (char_u *)"PageUp"},
  1804.     {K_PAGEDOWN,    (char_u *)"PageDown"},
  1805.     {K_KPAGEUP,        (char_u *)"kPageUp"},
  1806.     {K_KPAGEDOWN,    (char_u *)"kPageDown"},
  1807.  
  1808.     {K_KPLUS,        (char_u *)"kPlus"},
  1809.     {K_KMINUS,        (char_u *)"kMinus"},
  1810.     {K_KDIVIDE,        (char_u *)"kDivide"},
  1811.     {K_KMULTIPLY,    (char_u *)"kMultiply"},
  1812.     {K_KENTER,        (char_u *)"kEnter"},
  1813.     {K_KPOINT,        (char_u *)"kPoint"},
  1814.  
  1815.     {K_K0,        (char_u *)"k0"},
  1816.     {K_K1,        (char_u *)"k1"},
  1817.     {K_K2,        (char_u *)"k2"},
  1818.     {K_K3,        (char_u *)"k3"},
  1819.     {K_K4,        (char_u *)"k4"},
  1820.     {K_K5,        (char_u *)"k5"},
  1821.     {K_K6,        (char_u *)"k6"},
  1822.     {K_K7,        (char_u *)"k7"},
  1823.     {K_K8,        (char_u *)"k8"},
  1824.     {K_K9,        (char_u *)"k9"},
  1825.  
  1826.     {'<',        (char_u *)"lt"},
  1827.  
  1828.     {K_MOUSE,        (char_u *)"Mouse"},
  1829.     {K_NETTERM_MOUSE,    (char_u *)"NetMouse"},
  1830.     {K_DEC_MOUSE,    (char_u *)"DecMouse"},
  1831.     {K_JSBTERM_MOUSE,    (char_u *)"JsbMouse"},
  1832.     {K_LEFTMOUSE,    (char_u *)"LeftMouse"},
  1833.     {K_LEFTMOUSE_NM,    (char_u *)"LeftMouseNM"},
  1834.     {K_LEFTDRAG,    (char_u *)"LeftDrag"},
  1835.     {K_LEFTRELEASE,    (char_u *)"LeftRelease"},
  1836.     {K_LEFTRELEASE_NM,    (char_u *)"LeftReleaseNM"},
  1837.     {K_MIDDLEMOUSE,    (char_u *)"MiddleMouse"},
  1838.     {K_MIDDLEDRAG,    (char_u *)"MiddleDrag"},
  1839.     {K_MIDDLERELEASE,    (char_u *)"MiddleRelease"},
  1840.     {K_RIGHTMOUSE,    (char_u *)"RightMouse"},
  1841.     {K_RIGHTDRAG,    (char_u *)"RightDrag"},
  1842.     {K_RIGHTRELEASE,    (char_u *)"RightRelease"},
  1843.     {K_MOUSEDOWN,    (char_u *)"MouseDown"},
  1844.     {K_MOUSEUP,        (char_u *)"MouseUp"},
  1845.     {K_ZERO,        (char_u *)"Nul"},
  1846. #ifdef FEAT_EVAL
  1847.     {K_SNR,        (char_u *)"SNR"},
  1848. #endif
  1849.     {K_PLUG,        (char_u *)"Plug"},
  1850.     {0,            NULL}
  1851. };
  1852.  
  1853. #define KEY_NAMES_TABLE_LEN (sizeof(key_names_table) / sizeof(struct key_name_entry))
  1854.  
  1855. #ifdef FEAT_MOUSE
  1856. static struct mousetable
  1857. {
  1858.     int        pseudo_code;    /* Code for pseudo mouse event */
  1859.     int        button;        /* Which mouse button is it? */
  1860.     int        is_click;        /* Is it a mouse button click event? */
  1861.     int        is_drag;        /* Is it a mouse drag event? */
  1862. } mouse_table[] =
  1863. {
  1864.     {(int)KE_LEFTMOUSE,        MOUSE_LEFT,    TRUE,    FALSE},
  1865. #ifdef FEAT_GUI
  1866.     {(int)KE_LEFTMOUSE_NM,    MOUSE_LEFT,    TRUE,    FALSE},
  1867. #endif
  1868.     {(int)KE_LEFTDRAG,        MOUSE_LEFT,    FALSE,    TRUE},
  1869.     {(int)KE_LEFTRELEASE,    MOUSE_LEFT,    FALSE,    FALSE},
  1870. #ifdef FEAT_GUI
  1871.     {(int)KE_LEFTRELEASE_NM,    MOUSE_LEFT,    FALSE,    FALSE},
  1872. #endif
  1873.     {(int)KE_MIDDLEMOUSE,    MOUSE_MIDDLE,    TRUE,    FALSE},
  1874.     {(int)KE_MIDDLEDRAG,    MOUSE_MIDDLE,    FALSE,    TRUE},
  1875.     {(int)KE_MIDDLERELEASE,    MOUSE_MIDDLE,    FALSE,    FALSE},
  1876.     {(int)KE_RIGHTMOUSE,    MOUSE_RIGHT,    TRUE,    FALSE},
  1877.     {(int)KE_RIGHTDRAG,        MOUSE_RIGHT,    FALSE,    TRUE},
  1878.     {(int)KE_RIGHTRELEASE,    MOUSE_RIGHT,    FALSE,    FALSE},
  1879.     /* DRAG without CLICK */
  1880.     {(int)KE_IGNORE,        MOUSE_RELEASE,    FALSE,    TRUE},
  1881.     /* RELEASE without CLICK */
  1882.     {(int)KE_IGNORE,        MOUSE_RELEASE,    FALSE,    FALSE},
  1883.     {0,                0,        0,    0},
  1884. };
  1885. #endif /* FEAT_MOUSE */
  1886.  
  1887. /*
  1888.  * Return the modifier mask bit (MOD_MASK_*) which corresponds to the given
  1889.  * modifier name ('S' for Shift, 'C' for Ctrl etc).
  1890.  */
  1891.     int
  1892. name_to_mod_mask(c)
  1893.     int        c;
  1894. {
  1895.     int        i;
  1896.  
  1897.     if (c > 0 && c <= 255)    /* avoid TO_UPPER() with number > 255 */
  1898.     {
  1899.     c = TO_UPPER(c);
  1900.     for (i = 0; mod_mask_table[i].mod_mask != 0; i++)
  1901.         if (c == mod_mask_table[i].name)
  1902.         return mod_mask_table[i].mod_flag;
  1903.     }
  1904.     return 0;
  1905. }
  1906.  
  1907. #if 0 /* not used */
  1908. /*
  1909.  * Decide whether the given key code (K_*) is a shifted special
  1910.  * key (by looking at mod_mask).  If it is, then return the appropriate shifted
  1911.  * key code, otherwise just return the character as is.
  1912.  */
  1913.     int
  1914. check_shifted_spec_key(c)
  1915.     int        c;
  1916. {
  1917.     return simplify_key(c, &mod_mask);
  1918. }
  1919. #endif
  1920.  
  1921. /*
  1922.  * Check if if there is a special key code for "key" that includes the
  1923.  * modifiers specified.
  1924.  */
  1925.     int
  1926. simplify_key(key, modifiers)
  1927.     int        key;
  1928.     int        *modifiers;
  1929. {
  1930.     int        i;
  1931.     int        key0;
  1932.     int        key1;
  1933.  
  1934.     if (*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))
  1935.     {
  1936.     /* TAB is a special case */
  1937.     if (key == TAB && (*modifiers & MOD_MASK_SHIFT))
  1938.     {
  1939.         *modifiers &= ~MOD_MASK_SHIFT;
  1940.         return K_S_TAB;
  1941.     }
  1942.     key0 = KEY2TERMCAP0(key);
  1943.     key1 = KEY2TERMCAP1(key);
  1944.     for (i = 0; modifier_keys_table[i] != NUL; i += MOD_KEYS_ENTRY_SIZE)
  1945.         if (key0 == modifier_keys_table[i + 3]
  1946.             && key1 == modifier_keys_table[i + 4]
  1947.             && (*modifiers & modifier_keys_table[i]))
  1948.         {
  1949.         *modifiers &= ~modifier_keys_table[i];
  1950.         return TERMCAP2KEY(modifier_keys_table[i + 1],
  1951.                            modifier_keys_table[i + 2]);
  1952.         }
  1953.     }
  1954.     return key;
  1955. }
  1956.  
  1957. /*
  1958.  * Return a string which contains the name of the given key when the given
  1959.  * modifiers are down.
  1960.  */
  1961.     char_u *
  1962. get_special_key_name(c, modifiers)
  1963.     int        c;
  1964.     int        modifiers;
  1965. {
  1966.     static char_u string[MAX_KEY_NAME_LEN + 1];
  1967.  
  1968.     int        i, idx;
  1969.     int        table_idx;
  1970.     char_u  *s;
  1971.  
  1972.     string[0] = '<';
  1973.     idx = 1;
  1974.  
  1975.     /* Key that stands for a normal character. */
  1976.     if (IS_SPECIAL(c) && KEY2TERMCAP0(c) == KS_KEY)
  1977.     c = KEY2TERMCAP1(c);
  1978.  
  1979.     /*
  1980.      * Translate shifted special keys into unshifted keys and set modifier.
  1981.      * Same for CTRL and ALT modifiers.
  1982.      */
  1983.     if (IS_SPECIAL(c))
  1984.     {
  1985.     for (i = 0; modifier_keys_table[i] != 0; i += MOD_KEYS_ENTRY_SIZE)
  1986.         if (       KEY2TERMCAP0(c) == modifier_keys_table[i + 1]
  1987.             && KEY2TERMCAP1(c) == modifier_keys_table[i + 2])
  1988.         {
  1989.         modifiers |= modifier_keys_table[i];
  1990.         c = TERMCAP2KEY(modifier_keys_table[i + 3],
  1991.                            modifier_keys_table[i + 4]);
  1992.         break;
  1993.         }
  1994.     }
  1995.  
  1996.     /* try to find the key in the special key table */
  1997.     table_idx = find_special_key_in_table(c);
  1998.  
  1999.     /*
  2000.      * When not a known special key, and not a printable character, try to
  2001.      * extract modifiers.
  2002.      */
  2003.     if (c > 0
  2004. #ifdef FEAT_MBYTE
  2005.         && (*mb_char2len)(c) == 1
  2006. #endif
  2007.        )
  2008.     {
  2009.     if (table_idx < 0
  2010.         && (!vim_isprintc(c) || (c & 0x7f) == ' ')
  2011.         && (c & 0x80))
  2012.     {
  2013.         c &= 0x7f;
  2014.         modifiers |= MOD_MASK_ALT;
  2015.         /* try again, to find the un-alted key in the special key table */
  2016.         table_idx = find_special_key_in_table(c);
  2017.     }
  2018.     if (table_idx < 0 && !vim_isprintc(c) && c < ' ')
  2019.     {
  2020. #ifdef EBCDIC
  2021.         c = CtrlChar(c);
  2022. #else
  2023.         c += '@';
  2024. #endif
  2025.         modifiers |= MOD_MASK_CTRL;
  2026.     }
  2027.     }
  2028.  
  2029.     /* translate the modifier into a string */
  2030.     for (i = 0; mod_mask_table[i].name != 'A'; i++)
  2031.     if ((modifiers & mod_mask_table[i].mod_mask)
  2032.                         == mod_mask_table[i].mod_flag)
  2033.     {
  2034.         string[idx++] = mod_mask_table[i].name;
  2035.         string[idx++] = (char_u)'-';
  2036.     }
  2037.  
  2038.     if (table_idx < 0)        /* unknown special key, may output t_xx */
  2039.     {
  2040.     if (IS_SPECIAL(c))
  2041.     {
  2042.         string[idx++] = 't';
  2043.         string[idx++] = '_';
  2044.         string[idx++] = KEY2TERMCAP0(c);
  2045.         string[idx++] = KEY2TERMCAP1(c);
  2046.     }
  2047.     /* Not a special key, only modifiers, output directly */
  2048.     else
  2049.     {
  2050. #ifdef FEAT_MBYTE
  2051.         if (has_mbyte && (*mb_char2len)(c) > 1)
  2052.         idx += (*mb_char2bytes)(c, string + idx);
  2053.         else
  2054. #endif
  2055.         if (vim_isprintc(c))
  2056.         string[idx++] = c;
  2057.         else
  2058.         {
  2059.         s = transchar(c);
  2060.         while (*s)
  2061.             string[idx++] = *s++;
  2062.         }
  2063.     }
  2064.     }
  2065.     else        /* use name of special key */
  2066.     {
  2067.     STRCPY(string + idx, key_names_table[table_idx].name);
  2068.     idx = (int)STRLEN(string);
  2069.     }
  2070.     string[idx++] = '>';
  2071.     string[idx] = NUL;
  2072.     return string;
  2073. }
  2074.  
  2075. /*
  2076.  * Try translating a <> name at (*srcp)[] to dst[].
  2077.  * Return the number of characters added to dst[], zero for no match.
  2078.  * If there is a match, srcp is advanced to after the <> name.
  2079.  * dst[] must be big enough to hold the result (up to six characters)!
  2080.  */
  2081.     int
  2082. trans_special(srcp, dst, keycode)
  2083.     char_u    **srcp;
  2084.     char_u    *dst;
  2085.     int        keycode; /* prefer key code, e.g. K_DEL instead of DEL */
  2086. {
  2087.     int        modifiers;
  2088.     int        key;
  2089.     int        dlen = 0;
  2090.  
  2091.     key = find_special_key(srcp, &modifiers, keycode);
  2092.     if (key == 0)
  2093.     return 0;
  2094.  
  2095.     /* Put the appropriate modifier in a string */
  2096.     if (modifiers != 0)
  2097.     {
  2098.     dst[dlen++] = K_SPECIAL;
  2099.     dst[dlen++] = KS_MODIFIER;
  2100.     dst[dlen++] = modifiers;
  2101.     }
  2102.  
  2103.     if (IS_SPECIAL(key))
  2104.     {
  2105.     dst[dlen++] = K_SPECIAL;
  2106.     dst[dlen++] = KEY2TERMCAP0(key);
  2107.     dst[dlen++] = KEY2TERMCAP1(key);
  2108.     }
  2109. #ifdef FEAT_MBYTE
  2110.     else if (has_mbyte && !keycode)
  2111.     dlen += (*mb_char2bytes)(key, dst + dlen);
  2112. #endif
  2113.     else if (keycode)
  2114.     dlen = (int)(add_char2buf(key, dst + dlen) - dst);
  2115.     else
  2116.     dst[dlen++] = key;
  2117.  
  2118.     return dlen;
  2119. }
  2120.  
  2121. /*
  2122.  * Try translating a <> name at (*srcp)[], return the key and modifiers.
  2123.  * srcp is advanced to after the <> name.
  2124.  * returns 0 if there is no match.
  2125.  */
  2126.     int
  2127. find_special_key(srcp, modp, keycode)
  2128.     char_u    **srcp;
  2129.     int        *modp;
  2130.     int        keycode; /* prefer key code, e.g. K_DEL instead of DEL */
  2131. {
  2132.     char_u    *last_dash;
  2133.     char_u    *end_of_name;
  2134.     char_u    *src;
  2135.     char_u    *bp;
  2136.     int        modifiers;
  2137.     int        bit;
  2138.     int        key;
  2139.     long_u    n;
  2140.  
  2141.     src = *srcp;
  2142.     if (src[0] != '<')
  2143.     return 0;
  2144.  
  2145.     /* Find end of modifier list */
  2146.     last_dash = src;
  2147.     for (bp = src + 1; *bp == '-' || vim_isIDc(*bp); bp++)
  2148.     {
  2149.     if (*bp == '-')
  2150.     {
  2151.         last_dash = bp;
  2152.         if (bp[1] != NUL && bp[2] == '>')
  2153.         ++bp;    /* anything accepted, like <C-?> */
  2154.     }
  2155.     if (bp[0] == 't' && bp[1] == '_' && bp[2] && bp[3])
  2156.         bp += 3;    /* skip t_xx, xx may be '-' or '>' */
  2157.     }
  2158.  
  2159.     if (*bp == '>')    /* found matching '>' */
  2160.     {
  2161.     end_of_name = bp + 1;
  2162.  
  2163.     if (STRNICMP(src + 1, "char-", 5) == 0 && isdigit(src[6]))
  2164.     {
  2165.         /* <Char-123> or <Char-033> or <Char-0x33> */
  2166.         vim_str2nr(src + 6, NULL, NULL, TRUE, TRUE, NULL, &n);
  2167.         *modp = 0;
  2168.         *srcp = end_of_name;
  2169.         return (int)n;
  2170.     }
  2171.  
  2172.     /* Which modifiers are given? */
  2173.     modifiers = 0x0;
  2174.     for (bp = src + 1; bp < last_dash; bp++)
  2175.     {
  2176.         if (*bp != '-')
  2177.         {
  2178.         bit = name_to_mod_mask(*bp);
  2179.         if (bit == 0x0)
  2180.             break;    /* Illegal modifier name */
  2181.         modifiers |= bit;
  2182.         }
  2183.     }
  2184.  
  2185.     /*
  2186.      * Legal modifier name.
  2187.      */
  2188.     if (bp >= last_dash)
  2189.     {
  2190.         /*
  2191.          * Modifier with single letter, or special key name.
  2192.          */
  2193.         if (modifiers != 0 && last_dash[2] == '>')
  2194.         key = last_dash[1];
  2195.         else
  2196.         key = get_special_key_code(last_dash + 1);
  2197.  
  2198.         /*
  2199.          * get_special_key_code() may return NUL for invalid
  2200.          * special key name.
  2201.          */
  2202.         if (key != NUL)
  2203.         {
  2204.         /*
  2205.          * Only use a modifier when there is no special key code that
  2206.          * includes the modifier.
  2207.          */
  2208.         key = simplify_key(key, &modifiers);
  2209.  
  2210.         if (!keycode)
  2211.         {
  2212.             /* don't want keycode, use single byte code */
  2213.             if (key == K_BS)
  2214.             key = BS;
  2215.             else if (key == K_DEL || key == K_KDEL)
  2216.             key = DEL;
  2217.         }
  2218.  
  2219.         /*
  2220.          * Normal Key with modifier: Try to make a single byte code.
  2221.          */
  2222.         if (!IS_SPECIAL(key))
  2223.             key = extract_modifiers(key, &modifiers);
  2224.  
  2225.         *modp = modifiers;
  2226.         *srcp = end_of_name;
  2227.         return key;
  2228.         }
  2229.     }
  2230.     }
  2231.     return 0;
  2232. }
  2233.  
  2234. /*
  2235.  * Try to include modifiers in the key.
  2236.  * Changes "Shift-a" to 'A', "Alt-A" to 0xc0, etc.
  2237.  */
  2238.     int
  2239. extract_modifiers(key, modp)
  2240.     int        key;
  2241.     int        *modp;
  2242. {
  2243.     int    modifiers = *modp;
  2244.  
  2245.     if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key))
  2246.     {
  2247.     key = TO_UPPER(key);
  2248.     modifiers &= ~MOD_MASK_SHIFT;
  2249.     }
  2250.     if ((modifiers & MOD_MASK_CTRL)
  2251. #ifdef EBCDIC
  2252.         /* * TODO: EBCDIC Better use:
  2253.          * && (Ctrl_chr(key) || key == '?')
  2254.          * ???  */
  2255.         && strchr("?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_", key)
  2256.                                != NULL
  2257. #else
  2258.         && ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))
  2259. #endif
  2260.         )
  2261.     {
  2262.     key = Ctrl_chr(key);
  2263.     modifiers &= ~MOD_MASK_CTRL;
  2264.     /* <C-@> is <Nul> */
  2265.     if (key == 0)
  2266.         key = K_ZERO;
  2267.     }
  2268.     if ((modifiers & MOD_MASK_ALT) && key < 0x80)
  2269.     {
  2270.     key |= 0x80;
  2271.     modifiers &= ~MOD_MASK_ALT;    /* remove the META modifier */
  2272.     }
  2273.  
  2274.     *modp = modifiers;
  2275.     return key;
  2276. }
  2277.  
  2278. /*
  2279.  * Try to find key "c" in the special key table.
  2280.  * Return the index when found, -1 when not found.
  2281.  */
  2282.     int
  2283. find_special_key_in_table(c)
  2284.     int        c;
  2285. {
  2286.     int        i;
  2287.  
  2288.     for (i = 0; key_names_table[i].name != NULL; i++)
  2289.     if (c == key_names_table[i].key)
  2290.         break;
  2291.     if (key_names_table[i].name == NULL)
  2292.     i = -1;
  2293.     return i;
  2294. }
  2295.  
  2296. /*
  2297.  * Find the special key with the given name (the given string does not have to
  2298.  * end with NUL, the name is assumed to end before the first non-idchar).
  2299.  * If the name starts with "t_" the next two characters are interpreted as a
  2300.  * termcap name.
  2301.  * Return the key code, or 0 if not found.
  2302.  */
  2303.     int
  2304. get_special_key_code(name)
  2305.     char_u  *name;
  2306. {
  2307.     char_u  *table_name;
  2308.     char_u  string[3];
  2309.     int        i, j;
  2310.  
  2311.     /*
  2312.      * If it's <t_xx> we get the code for xx from the termcap
  2313.      */
  2314.     if (name[0] == 't' && name[1] == '_' && name[2] != NUL && name[3] != NUL)
  2315.     {
  2316.     string[0] = name[2];
  2317.     string[1] = name[3];
  2318.     string[2] = NUL;
  2319.     if (add_termcap_entry(string, FALSE) == OK)
  2320.         return TERMCAP2KEY(name[2], name[3]);
  2321.     }
  2322.     else
  2323.     for (i = 0; key_names_table[i].name != NULL; i++)
  2324.     {
  2325.         table_name = key_names_table[i].name;
  2326.         for (j = 0; vim_isIDc(name[j]) && table_name[j] != NUL; j++)
  2327.         if (TO_LOWER(table_name[j]) != TO_LOWER(name[j]))
  2328.             break;
  2329.         if (!vim_isIDc(name[j]) && table_name[j] == NUL)
  2330.         return key_names_table[i].key;
  2331.     }
  2332.     return 0;
  2333. }
  2334.  
  2335. #ifdef FEAT_CMDL_COMPL
  2336.     char_u *
  2337. get_key_name(i)
  2338.     int        i;
  2339. {
  2340.     if (i >= KEY_NAMES_TABLE_LEN)
  2341.     return NULL;
  2342.     return  key_names_table[i].name;
  2343. }
  2344. #endif
  2345.  
  2346. #ifdef FEAT_MOUSE
  2347. /*
  2348.  * Look up the given mouse code to return the relevant information in the other
  2349.  * arguments.  Return which button is down or was released.
  2350.  */
  2351.     int
  2352. get_mouse_button(code, is_click, is_drag)
  2353.     int        code;
  2354.     int        *is_click;
  2355.     int        *is_drag;
  2356. {
  2357.     int        i;
  2358.  
  2359.     for (i = 0; mouse_table[i].pseudo_code; i++)
  2360.     if (code == mouse_table[i].pseudo_code)
  2361.     {
  2362.         *is_click = mouse_table[i].is_click;
  2363.         *is_drag = mouse_table[i].is_drag;
  2364.         return mouse_table[i].button;
  2365.     }
  2366.     return 0;        /* Shouldn't get here */
  2367. }
  2368.  
  2369. /*
  2370.  * Return the appropriate pseudo mouse event token (KE_LEFTMOUSE etc) based on
  2371.  * the given information about which mouse button is down, and whether the
  2372.  * mouse was clicked, dragged or released.
  2373.  */
  2374.     int
  2375. get_pseudo_mouse_code(button, is_click, is_drag)
  2376.     int        button;    /* eg MOUSE_LEFT */
  2377.     int        is_click;
  2378.     int        is_drag;
  2379. {
  2380.     int        i;
  2381.  
  2382.     for (i = 0; mouse_table[i].pseudo_code; i++)
  2383.     if (button == mouse_table[i].button
  2384.         && is_click == mouse_table[i].is_click
  2385.         && is_drag == mouse_table[i].is_drag)
  2386.     {
  2387. #ifdef FEAT_GUI
  2388.         /* Trick: a non mappable left click and release has mouse_col < 0.
  2389.          * Used for 'mousefocus' in gui_mouse_moved() */
  2390.         if (mouse_col < 0)
  2391.         {
  2392.         mouse_col = 0;
  2393.         if (mouse_table[i].pseudo_code == (int)KE_LEFTMOUSE)
  2394.             return (int)KE_LEFTMOUSE_NM;
  2395.         if (mouse_table[i].pseudo_code == (int)KE_LEFTRELEASE)
  2396.             return (int)KE_LEFTRELEASE_NM;
  2397.         }
  2398. #endif
  2399.         return mouse_table[i].pseudo_code;
  2400.     }
  2401.     return (int)KE_IGNORE;        /* not recongnized, ignore it */
  2402. }
  2403. #endif /* FEAT_MOUSE */
  2404.  
  2405. /*
  2406.  * Return the current end-of-line type: EOL_DOS, EOL_UNIX or EOL_MAC.
  2407.  */
  2408.     int
  2409. get_fileformat(buf)
  2410.     buf_T    *buf;
  2411. {
  2412.     int        c = *buf->b_p_ff;
  2413.  
  2414.     if (buf->b_p_bin || c == 'u')
  2415.     return EOL_UNIX;
  2416.     if (c == 'm')
  2417.     return EOL_MAC;
  2418.     return EOL_DOS;
  2419. }
  2420.  
  2421. /*
  2422.  * Like get_fileformat(), but override 'fileformat' with "p" for "++opt=val"
  2423.  * argument.
  2424.  */
  2425.     int
  2426. get_fileformat_force(buf, eap)
  2427.     buf_T    *buf;
  2428.     exarg_T    *eap;        /* can be NULL! */
  2429. {
  2430.     int        c;
  2431.  
  2432.     if (eap != NULL && eap->force_ff != 0)
  2433.     c = eap->cmd[eap->force_ff];
  2434.     else
  2435.     {
  2436.     if (buf->b_p_bin)
  2437.         return EOL_UNIX;
  2438.     c = *buf->b_p_ff;
  2439.     }
  2440.     if (c == 'u')
  2441.     return EOL_UNIX;
  2442.     if (c == 'm')
  2443.     return EOL_MAC;
  2444.     return EOL_DOS;
  2445. }
  2446.  
  2447. /*
  2448.  * Set the current end-of-line type to EOL_DOS, EOL_UNIX or EOL_MAC.
  2449.  * Sets both 'textmode' and 'fileformat'.
  2450.  * Note: Does _not_ set global value of 'textmode'!
  2451.  */
  2452.     void
  2453. set_fileformat(t, opt_flags)
  2454.     int        t;
  2455.     int        opt_flags;    /* OPT_LOCAL and/or OPT_GLOBAL */
  2456. {
  2457.     char    *p = NULL;
  2458.  
  2459.     switch (t)
  2460.     {
  2461.     case EOL_DOS:
  2462.     p = FF_DOS;
  2463.     curbuf->b_p_tx = TRUE;
  2464.     break;
  2465.     case EOL_UNIX:
  2466.     p = FF_UNIX;
  2467.     curbuf->b_p_tx = FALSE;
  2468.     break;
  2469.     case EOL_MAC:
  2470.     p = FF_MAC;
  2471.     curbuf->b_p_tx = FALSE;
  2472.     break;
  2473.     }
  2474.     if (p != NULL)
  2475.     set_string_option_direct((char_u *)"ff", -1, (char_u *)p,
  2476.                             OPT_FREE | opt_flags);
  2477. #ifdef FEAT_WINDOWS
  2478.     check_status(curbuf);
  2479. #endif
  2480. #ifdef FEAT_TITLE
  2481.     need_maketitle = TRUE;        /* set window title later */
  2482. #endif
  2483. }
  2484.  
  2485. /*
  2486.  * Return the default fileformat from 'fileformats'.
  2487.  */
  2488.     int
  2489. default_fileformat()
  2490. {
  2491.     switch (*p_ffs)
  2492.     {
  2493.     case 'm':   return EOL_MAC;
  2494.     case 'd':   return EOL_DOS;
  2495.     }
  2496.     return EOL_UNIX;
  2497. }
  2498.  
  2499. /*
  2500.  * Call shell.    Calls mch_call_shell, with 'shellxquote' added.
  2501.  */
  2502.     int
  2503. call_shell(cmd, opt)
  2504.     char_u    *cmd;
  2505.     int        opt;
  2506. {
  2507.     char_u    *ncmd;
  2508.     int        retval;
  2509.  
  2510.     if (p_verbose > 3)
  2511.     smsg((char_u *)_("Calling shell to execute: \"%s\""), cmd);
  2512.  
  2513.     if (*p_sh == NUL)
  2514.     {
  2515.     EMSG(_(e_shellempty));
  2516.     retval = -1;
  2517.     }
  2518.     else
  2519.     {
  2520. #ifdef FEAT_GUI_MSWIN
  2521.     /* Don't hide the pointer while executing a shell command. */
  2522.     gui_mch_mousehide(FALSE);
  2523. #endif
  2524. #ifdef FEAT_GUI
  2525.     ++hold_gui_events;
  2526. #endif
  2527.     /* The external command may update a tags file, clear cached tags. */
  2528.     tag_freematch();
  2529.  
  2530.     if (cmd == NULL || *p_sxq == NUL)
  2531.         retval = mch_call_shell(cmd, opt);
  2532.     else
  2533.     {
  2534.         ncmd = alloc((unsigned)(STRLEN(cmd) + STRLEN(p_sxq) * 2 + 1));
  2535.         if (ncmd != NULL)
  2536.         {
  2537.         STRCPY(ncmd, p_sxq);
  2538.         STRCAT(ncmd, cmd);
  2539.         STRCAT(ncmd, p_sxq);
  2540.         retval = mch_call_shell(ncmd, opt);
  2541.         vim_free(ncmd);
  2542.         }
  2543.         else
  2544.         retval = -1;
  2545.     }
  2546. #ifdef FEAT_GUI
  2547.     --hold_gui_events;
  2548. #endif
  2549.     /*
  2550.      * Check the window size, in case it changed while executing the
  2551.      * external command.
  2552.      */
  2553.     shell_resized_check();
  2554.     }
  2555.  
  2556. #ifdef FEAT_EVAL
  2557.     set_vim_var_nr(VV_SHELL_ERROR, (long)retval);
  2558. #endif
  2559.  
  2560.     return retval;
  2561. }
  2562.  
  2563. /*
  2564.  * VISUAL and OP_PENDING State are never set, they are equal to NORMAL State
  2565.  * with a condition.  This function returns the real State.
  2566.  */
  2567.     int
  2568. get_real_state()
  2569. {
  2570.     if (State & NORMAL)
  2571.     {
  2572. #ifdef FEAT_VISUAL
  2573.     if (VIsual_active)
  2574.         return VISUAL;
  2575.     else
  2576. #endif
  2577.         if (finish_op)
  2578.         return OP_PENDING;
  2579.     }
  2580.     return State;
  2581. }
  2582.  
  2583. #if defined(FEAT_SESSION) || defined(MSWIN) \
  2584.     || (defined(FEAT_GUI_GTK) && defined(FEAT_WINDOWS)) \
  2585.     || defined(FEAT_SUN_WORKSHOP) || defined(PROTO)
  2586. /*
  2587.  * Change to a file's directory.
  2588.  * Caller must call shorten_fnames()!
  2589.  * Return OK or FAIL.
  2590.  */
  2591.     int
  2592. vim_chdirfile(fname)
  2593.     char_u    *fname;
  2594. {
  2595.     char_u    temp_string[MAXPATHL];
  2596.     char_u    *p;
  2597.     char_u    *t;
  2598.  
  2599.     STRCPY(temp_string, fname);
  2600.     p = get_past_head(temp_string);
  2601.     t = gettail(temp_string);
  2602.     while (t > p && vim_ispathsep(t[-1]))
  2603.     --t;
  2604.     *t = NUL; /* chop off end of string */
  2605.  
  2606.     return mch_chdir((char *)temp_string) == 0 ? OK : FAIL;
  2607. }
  2608. #endif
  2609.  
  2610. #if defined(CURSOR_SHAPE) || defined(PROTO)
  2611.  
  2612. /*
  2613.  * Handling of cursor and mouse pointer shapes in various modes.
  2614.  */
  2615.  
  2616. cursorentry_T shape_table[SHAPE_IDX_COUNT] =
  2617. {
  2618.     /* The values will be filled in from the 'guicursor' and 'mouseshape'
  2619.      * defaults when Vim starts.
  2620.      * Adjust the SHAPE_IDX_ defines when making changes! */
  2621.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "n", SHAPE_CURSOR+SHAPE_MOUSE},
  2622.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "v", SHAPE_CURSOR+SHAPE_MOUSE},
  2623.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "i", SHAPE_CURSOR+SHAPE_MOUSE},
  2624.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "r", SHAPE_CURSOR+SHAPE_MOUSE},
  2625.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "c", SHAPE_CURSOR+SHAPE_MOUSE},
  2626.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "ci", SHAPE_CURSOR+SHAPE_MOUSE},
  2627.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "cr", SHAPE_CURSOR+SHAPE_MOUSE},
  2628.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "o", SHAPE_CURSOR+SHAPE_MOUSE},
  2629.     {0,    0, 0, 700L, 400L, 250L, 0, 0, "ve", SHAPE_CURSOR+SHAPE_MOUSE},
  2630.     {0,    0, 0,   0L,   0L,   0L, 0, 0, "e", SHAPE_MOUSE},
  2631.     {0,    0, 0,   0L,   0L,   0L, 0, 0, "s", SHAPE_MOUSE},
  2632.     {0,    0, 0,   0L,   0L,   0L, 0, 0, "sd", SHAPE_MOUSE},
  2633.     {0,    0, 0,   0L,   0L,   0L, 0, 0, "vs", SHAPE_MOUSE},
  2634.     {0,    0, 0,   0L,   0L,   0L, 0, 0, "vd", SHAPE_MOUSE},
  2635.     {0,    0, 0,   0L,   0L,   0L, 0, 0, "m", SHAPE_MOUSE},
  2636.     {0,    0, 0, 100L, 100L, 100L, 0, 0, "sm", SHAPE_CURSOR},
  2637. };
  2638.  
  2639. #ifdef FEAT_MOUSESHAPE
  2640. /*
  2641.  * Table with names for mouse shapes.  Keep in sync with all the tables for
  2642.  * mch_set_mouse_shape()!.
  2643.  */
  2644. static char * mshape_names[] =
  2645. {
  2646.     "arrow",    /* default, must be the first one */
  2647.     "blank",    /* hidden */
  2648.     "beam",
  2649.     "updown",
  2650.     "udsizing",
  2651.     "leftright",
  2652.     "lrsizing",
  2653.     "busy",
  2654.     "no",
  2655.     "crosshair",
  2656.     "hand1",
  2657.     "hand2",
  2658.     "pencil",
  2659.     "question",
  2660.     "rightup-arrow",
  2661.     "up-arrow",
  2662.     NULL
  2663. };
  2664. #endif
  2665.  
  2666. /*
  2667.  * Parse the 'guicursor' option ("what" is SHAPE_CURSOR) or 'mouseshape'
  2668.  * ("what" is SHAPE_MOUSE).
  2669.  * Returns error message for an illegal option, NULL otherwise.
  2670.  */
  2671.     char_u *
  2672. parse_shape_opt(what)
  2673.     int        what;
  2674. {
  2675.     char_u    *modep;
  2676.     char_u    *colonp;
  2677.     char_u    *commap;
  2678.     char_u    *slashp;
  2679.     char_u    *p, *endp;
  2680.     int        idx = 0;        /* init for GCC */
  2681.     int        all_idx;
  2682.     int        len;
  2683.     int        i;
  2684.     long    n;
  2685.     int        found_ve = FALSE;    /* found "ve" flag */
  2686.     int        round;
  2687.  
  2688.     /*
  2689.      * First round: check for errors; second round: do it for real.
  2690.      */
  2691.     for (round = 1; round <= 2; ++round)
  2692.     {
  2693.     /*
  2694.      * Repeat for all comma separated parts.
  2695.      */
  2696. #ifdef FEAT_MOUSESHAPE
  2697.     if (what == SHAPE_MOUSE)
  2698.         modep = p_mouseshape;
  2699.     else
  2700. #endif
  2701.         modep = p_guicursor;
  2702.     while (*modep != NUL)
  2703.     {
  2704.         colonp = vim_strchr(modep, ':');
  2705.         if (colonp == NULL)
  2706.         return (char_u *)N_("Missing colon");
  2707.         if (colonp == modep)
  2708.         return (char_u *)N_("Illegal mode");
  2709.         commap = vim_strchr(modep, ',');
  2710.  
  2711.         /*
  2712.          * Repeat for all mode's before the colon.
  2713.          * For the 'a' mode, we loop to handle all the modes.
  2714.          */
  2715.         all_idx = -1;
  2716.         while (modep < colonp || all_idx >= 0)
  2717.         {
  2718.         if (all_idx < 0)
  2719.         {
  2720.             /* Find the mode. */
  2721.             if (modep[1] == '-' || modep[1] == ':')
  2722.             len = 1;
  2723.             else
  2724.             len = 2;
  2725.             if (len == 1 && TO_LOWER(modep[0]) == 'a')
  2726.             all_idx = SHAPE_IDX_COUNT - 1;
  2727.             else
  2728.             {
  2729.             for (idx = 0; idx < SHAPE_IDX_COUNT; ++idx)
  2730.                 if (STRNICMP(modep, shape_table[idx].name, len)
  2731.                                      == 0)
  2732.                 break;
  2733.             if (idx == SHAPE_IDX_COUNT
  2734.                    || (shape_table[idx].used_for & what) == 0)
  2735.                 return (char_u *)N_("Illegal mode");
  2736.             if (len == 2 && modep[0] == 'v' && modep[1] == 'e')
  2737.                 found_ve = TRUE;
  2738.             }
  2739.             modep += len + 1;
  2740.         }
  2741.  
  2742.         if (all_idx >= 0)
  2743.             idx = all_idx--;
  2744.         else if (round == 2)
  2745.         {
  2746. #ifdef FEAT_MOUSESHAPE
  2747.             if (what == SHAPE_MOUSE)
  2748.             {
  2749.             /* Set the default, for the missing parts */
  2750.             shape_table[idx].mshape = 0;
  2751.             }
  2752.             else
  2753. #endif
  2754.             {
  2755.             /* Set the defaults, for the missing parts */
  2756.             shape_table[idx].shape = SHAPE_BLOCK;
  2757.             shape_table[idx].blinkwait = 700L;
  2758.             shape_table[idx].blinkon = 400L;
  2759.             shape_table[idx].blinkoff = 250L;
  2760.             }
  2761.         }
  2762.  
  2763.         /* Parse the part after the colon */
  2764.         for (p = colonp + 1; *p && *p != ','; )
  2765.         {
  2766. #ifdef FEAT_MOUSESHAPE
  2767.             if (what == SHAPE_MOUSE)
  2768.             {
  2769.             for (i = 0; ; ++i)
  2770.             {
  2771.                 if (mshape_names[i] == NULL)
  2772.                 {
  2773.                 if (!isdigit(*p))
  2774.                     return (char_u *)N_("Illegal mouseshape");
  2775.                 if (round == 2)
  2776.                     shape_table[idx].mshape =
  2777.                           getdigits(&p) + MSHAPE_NUMBERED;
  2778.                 else
  2779.                     (void)getdigits(&p);
  2780.                 break;
  2781.                 }
  2782.                 len = (int)STRLEN(mshape_names[i]);
  2783.                 if (STRNICMP(p, mshape_names[i], len) == 0)
  2784.                 {
  2785.                 if (round == 2)
  2786.                     shape_table[idx].mshape = i;
  2787.                 p += len;
  2788.                 break;
  2789.                 }
  2790.             }
  2791.             }
  2792.             else /* if (what == SHAPE_MOUSE) */
  2793. #endif
  2794.             {
  2795.             /*
  2796.              * First handle the ones with a number argument.
  2797.              */
  2798.             i = *p;
  2799.             len = 0;
  2800.             if (STRNICMP(p, "ver", 3) == 0)
  2801.                 len = 3;
  2802.             else if (STRNICMP(p, "hor", 3) == 0)
  2803.                 len = 3;
  2804.             else if (STRNICMP(p, "blinkwait", 9) == 0)
  2805.                 len = 9;
  2806.             else if (STRNICMP(p, "blinkon", 7) == 0)
  2807.                 len = 7;
  2808.             else if (STRNICMP(p, "blinkoff", 8) == 0)
  2809.                 len = 8;
  2810.             if (len != 0)
  2811.             {
  2812.                 p += len;
  2813.                 if (!isdigit(*p))
  2814.                 return (char_u *)N_("digit expected");
  2815.                 n = getdigits(&p);
  2816.                 if (len == 3)   /* "ver" or "hor" */
  2817.                 {
  2818.                 if (n == 0)
  2819.                     return (char_u *)N_("Illegal percentage");
  2820.                 if (round == 2)
  2821.                 {
  2822.                     if (TO_LOWER(i) == 'v')
  2823.                     shape_table[idx].shape = SHAPE_VER;
  2824.                     else
  2825.                     shape_table[idx].shape = SHAPE_HOR;
  2826.                     shape_table[idx].percentage = n;
  2827.                 }
  2828.                 }
  2829.                 else if (round == 2)
  2830.                 {
  2831.                 if (len == 9)
  2832.                     shape_table[idx].blinkwait = n;
  2833.                 else if (len == 7)
  2834.                     shape_table[idx].blinkon = n;
  2835.                 else
  2836.                     shape_table[idx].blinkoff = n;
  2837.                 }
  2838.             }
  2839.             else if (STRNICMP(p, "block", 5) == 0)
  2840.             {
  2841.                 if (round == 2)
  2842.                 shape_table[idx].shape = SHAPE_BLOCK;
  2843.                 p += 5;
  2844.             }
  2845.             else    /* must be a highlight group name then */
  2846.             {
  2847.                 endp = vim_strchr(p, '-');
  2848.                 if (commap == NULL)            /* last part */
  2849.                 {
  2850.                 if (endp == NULL)
  2851.                     endp = p + STRLEN(p);   /* find end of part */
  2852.                 }
  2853.                 else if (endp > commap || endp == NULL)
  2854.                 endp = commap;
  2855.                 slashp = vim_strchr(p, '/');
  2856.                 if (slashp != NULL && slashp < endp)
  2857.                 {
  2858.                 /* "group/langmap_group" */
  2859.                 i = syn_check_group(p, (int)(slashp - p));
  2860.                 p = slashp + 1;
  2861.                 }
  2862.                 if (round == 2)
  2863.                 {
  2864.                 shape_table[idx].id = syn_check_group(p,
  2865.                                  (int)(endp - p));
  2866.                 shape_table[idx].id_lm = shape_table[idx].id;
  2867.                 if (slashp != NULL && slashp < endp)
  2868.                     shape_table[idx].id = i;
  2869.                 }
  2870.                 p = endp;
  2871.             }
  2872.             } /* if (what != SHAPE_MOUSE) */
  2873.  
  2874.             if (*p == '-')
  2875.             ++p;
  2876.         }
  2877.         }
  2878.         modep = p;
  2879.         if (*modep == ',')
  2880.         ++modep;
  2881.     }
  2882.     }
  2883.  
  2884.     /* If the 's' flag is not given, use the 'v' cursor for 's' */
  2885.     if (!found_ve)
  2886.     {
  2887. #ifdef FEAT_MOUSESHAPE
  2888.     if (what == SHAPE_MOUSE)
  2889.     {
  2890.         shape_table[SHAPE_IDX_VE].mshape = shape_table[SHAPE_IDX_V].mshape;
  2891.     }
  2892.     else
  2893. #endif
  2894.     {
  2895.         shape_table[SHAPE_IDX_VE].shape = shape_table[SHAPE_IDX_V].shape;
  2896.         shape_table[SHAPE_IDX_VE].percentage =
  2897.                      shape_table[SHAPE_IDX_V].percentage;
  2898.         shape_table[SHAPE_IDX_VE].blinkwait =
  2899.                       shape_table[SHAPE_IDX_V].blinkwait;
  2900.         shape_table[SHAPE_IDX_VE].blinkon =
  2901.                         shape_table[SHAPE_IDX_V].blinkon;
  2902.         shape_table[SHAPE_IDX_VE].blinkoff =
  2903.                        shape_table[SHAPE_IDX_V].blinkoff;
  2904.         shape_table[SHAPE_IDX_VE].id = shape_table[SHAPE_IDX_V].id;
  2905.         shape_table[SHAPE_IDX_VE].id_lm = shape_table[SHAPE_IDX_V].id_lm;
  2906.     }
  2907.     }
  2908.  
  2909.     return NULL;
  2910. }
  2911.  
  2912. /*
  2913.  * Return the index into shape_table[] for the current mode.
  2914.  * When "mouse" is TRUE, consider indexes valid for the mouse pointer.
  2915.  */
  2916.     int
  2917. get_shape_idx(mouse)
  2918.     int    mouse;
  2919. {
  2920. #ifdef FEAT_MOUSESHAPE
  2921.     if (mouse && (State == HITRETURN || State == ASKMORE))
  2922.     return SHAPE_IDX_MORE;
  2923.     if (mouse && drag_status_line)
  2924.     return SHAPE_IDX_SDRAG;
  2925. # ifdef FEAT_VERTSPLIT
  2926.     if (mouse && drag_sep_line)
  2927.     return SHAPE_IDX_VDRAG;
  2928. # endif
  2929. #endif
  2930.     if (!mouse && State == SHOWMATCH)
  2931.     return SHAPE_IDX_SM;
  2932. #ifdef FEAT_VREPLACE
  2933.     if (State & VREPLACE_FLAG)
  2934.     return SHAPE_IDX_R;
  2935. #endif
  2936.     if (State & REPLACE_FLAG)
  2937.     return SHAPE_IDX_R;
  2938.     if (State & INSERT)
  2939.     return SHAPE_IDX_I;
  2940.     if (State & CMDLINE)
  2941.     {
  2942.     if (cmdline_at_end())
  2943.         return SHAPE_IDX_C;
  2944.     if (cmdline_overstrike())
  2945.         return SHAPE_IDX_CR;
  2946.     return SHAPE_IDX_CI;
  2947.     }
  2948.     if (finish_op)
  2949.     return SHAPE_IDX_O;
  2950. #ifdef FEAT_VISUAL
  2951.     if (VIsual_active)
  2952.     {
  2953.     if (*p_sel == 'e')
  2954.         return SHAPE_IDX_VE;
  2955.     else
  2956.         return SHAPE_IDX_V;
  2957.     }
  2958. #endif
  2959.     return SHAPE_IDX_N;
  2960. }
  2961.  
  2962. # if defined(FEAT_MOUSESHAPE) || defined(PROTO)
  2963. static int old_mouse_shape = 0;
  2964.  
  2965. /*
  2966.  * Set the mouse shape:
  2967.  * If "shape" is -1, use shape depending on the current mode,
  2968.  * depending on the current state.
  2969.  * If "shape" is -2, only update the shape when it's CLINE or STATUS (used
  2970.  * when the mouse moves off the status or command line).
  2971.  */
  2972.     void
  2973. update_mouseshape(shape_idx)
  2974.     int    shape_idx;
  2975. {
  2976.     int new_mouse_shape;
  2977.  
  2978.     /* Only works in GUI mode. */
  2979.     if (!gui.in_use)
  2980.     return;
  2981.  
  2982.     /* Postpone the updating when more is to come.  Speeds up executing of
  2983.      * mappings. */
  2984.     if (shape_idx == -1 && char_avail())
  2985.     {
  2986.     postponed_mouseshape = TRUE;
  2987.     return;
  2988.     }
  2989.  
  2990.     if (shape_idx == -2
  2991.         && old_mouse_shape != shape_table[SHAPE_IDX_CLINE].mshape
  2992.         && old_mouse_shape != shape_table[SHAPE_IDX_STATUS].mshape
  2993.         && old_mouse_shape != shape_table[SHAPE_IDX_VSEP].mshape)
  2994.     return;
  2995.     if (shape_idx < 0)
  2996.     new_mouse_shape = shape_table[get_shape_idx(TRUE)].mshape;
  2997.     else
  2998.     new_mouse_shape = shape_table[shape_idx].mshape;
  2999.     if (new_mouse_shape != old_mouse_shape)
  3000.     {
  3001.     mch_set_mouse_shape(new_mouse_shape);
  3002.     old_mouse_shape = new_mouse_shape;
  3003.     }
  3004.     postponed_mouseshape = FALSE;
  3005. }
  3006. # endif
  3007.  
  3008. #endif /* CURSOR_SHAPE */
  3009.  
  3010.  
  3011. #ifdef FEAT_CRYPT
  3012. /*
  3013.  * Optional encryption suypport.
  3014.  * Mohsin Ahmed, mosh@sasi.com, 98-09-24
  3015.  * Based on zip/crypt sources.
  3016.  *
  3017.  * NOTE FOR USA: Since 2000 exporting this code from the USA is allowed to
  3018.  * most countries.  There are a few exceptions, but that still should not be a
  3019.  * problem since this code was originally created in Europe and India.
  3020.  */
  3021.  
  3022. /* from zip.h */
  3023.  
  3024. typedef unsigned short ush;    /* unsigned 16-bit value */
  3025. typedef unsigned long  ulg;    /* unsigned 32-bit value */
  3026.  
  3027. static void make_crc_tab __ARGS((void));
  3028.  
  3029. ulg crc_32_tab[256];
  3030.  
  3031. /*
  3032.  * Fill the CRC table.
  3033.  */
  3034.     static void
  3035. make_crc_tab()
  3036. {
  3037.     ulg        s,t,v;
  3038.     static int    done = FALSE;
  3039.  
  3040.     if (done)
  3041.     return;
  3042.     for (t = 0; t < 256; t++)
  3043.     {
  3044.     v = t;
  3045.     for (s = 0; s < 8; s++)
  3046.         v = (v >> 1) ^ ((v & 1) * (ulg)0xedb88320L);
  3047.     crc_32_tab[t] = v;
  3048.     }
  3049.     done = TRUE;
  3050. }
  3051.  
  3052. #define CRC32(c, b) (crc_32_tab[((int)(c) ^ (b)) & 0xff] ^ ((c) >> 8))
  3053.  
  3054.  
  3055. static ulg keys[3]; /* keys defining the pseudo-random sequence */
  3056.  
  3057. /*
  3058.  * Return the next byte in the pseudo-random sequence
  3059.  */
  3060.     int
  3061. decrypt_byte()
  3062. {
  3063.     ush temp;
  3064.  
  3065.     temp = (ush)keys[2] | 2;
  3066.     return (int)(((unsigned)(temp * (temp ^ 1)) >> 8) & 0xff);
  3067. }
  3068.  
  3069. /*
  3070.  * Update the encryption keys with the next byte of plain text
  3071.  */
  3072.     int
  3073. update_keys(c)
  3074.     int c;            /* byte of plain text */
  3075. {
  3076.     keys[0] = CRC32(keys[0], c);
  3077.     keys[1] += keys[0] & 0xff;
  3078.     keys[1] = keys[1] * 134775813L + 1;
  3079.     keys[2] = CRC32(keys[2], (int)(keys[1] >> 24));
  3080.     return c;
  3081. }
  3082.  
  3083. /*
  3084.  * Initialize the encryption keys and the random header according to
  3085.  * the given password.
  3086.  * If "passwd" is NULL or empty, don't do anything.
  3087.  */
  3088.     void
  3089. crypt_init_keys(passwd)
  3090.     char_u *passwd;        /* password string with which to modify keys */
  3091. {
  3092.     if (passwd != NULL && *passwd != NUL)
  3093.     {
  3094.     make_crc_tab();
  3095.     keys[0] = 305419896L;
  3096.     keys[1] = 591751049L;
  3097.     keys[2] = 878082192L;
  3098.     while (*passwd != '\0')
  3099.         update_keys((int)*passwd++);
  3100.     }
  3101. }
  3102.  
  3103. /*
  3104.  * Ask the user for a crypt key.
  3105.  * When "store" is TRUE, the new key in stored in the 'key' option, and the
  3106.  * 'key' option value is returned: Don't free it.
  3107.  * When "store" is FALSE, the typed key is returned in allocated memory.
  3108.  * Returns NULL on failure.
  3109.  */
  3110.     char_u *
  3111. get_crypt_key(store, twice)
  3112.     int        store;
  3113.     int        twice;        /* Ask for the key twice. */
  3114. {
  3115.     char_u    *p1, *p2 = NULL;
  3116.     int        round;
  3117.  
  3118.     for (round = 0; ; ++round)
  3119.     {
  3120.     cmdline_star = TRUE;
  3121.     cmdline_row = msg_row;
  3122.     p1 = getcmdline_prompt(NUL, round == 0
  3123.         ? (char_u *)_("Enter encryption key: ")
  3124.         : (char_u *)_("Enter same key again: "), 0);
  3125.     cmdline_star = FALSE;
  3126.  
  3127.     if (p1 == NULL)
  3128.         break;
  3129.  
  3130.     if (round == twice)
  3131.     {
  3132.         if (p2 != NULL && STRCMP(p1, p2) != 0)
  3133.         {
  3134.         MSG(_("Keys don't match!"));
  3135.         vim_free(p1);
  3136.         vim_free(p2);
  3137.         p2 = NULL;
  3138.         round = -1;        /* do it again */
  3139.         continue;
  3140.         }
  3141.         if (store)
  3142.         {
  3143.         set_option_value((char_u *)"key", 0L, p1, OPT_LOCAL);
  3144.         vim_free(p1);
  3145.         p1 = curbuf->b_p_key;
  3146.         }
  3147.         break;
  3148.     }
  3149.     p2 = p1;
  3150.     }
  3151.  
  3152.     /* since the user typed this, no need to wait for return */
  3153.     need_wait_return = FALSE;
  3154.     msg_didout = FALSE;
  3155.  
  3156.     vim_free(p2);
  3157.     return p1;
  3158. }
  3159.  
  3160. #endif /* FEAT_CRYPT */
  3161.  
  3162. /* TODO: make some #ifdef for this */
  3163. /*--------[ file searching ]-------------------------------------------------*/
  3164. /*
  3165.  * File searching functions for 'path', 'tags' and 'cdpath' options.
  3166.  * External visible functions:
  3167.  * vim_findfile_init()        creates/initialises the search context
  3168.  * vim_findfile_free_visited()    free list of visited files/dirs of search
  3169.  *                context
  3170.  * vim_findfile()        find a file in the search context
  3171.  * vim_findfile_cleanup()    cleanup/free search context created by
  3172.  *                vim_findfile_init()
  3173.  *
  3174.  * All static functions and variables start with 'ff_'
  3175.  *
  3176.  * In general it works like this:
  3177.  * First you create yourself a search context by calling vim_findfile_init().
  3178.  * It is possible to give a search context from a previous call to
  3179.  * vim_findfile_init(), so it can be reused. After this you call vim_findfile()
  3180.  * until you are satisfied with the result or it returns NULL. On every call it
  3181.  * returns the next file which matches the conditions given to
  3182.  * vim_findfile_init(). If it doesn't find a next file it returns NULL.
  3183.  *
  3184.  * It is possible to call vim_findfile_init() again to reinitialise your search
  3185.  * with some new parameters. Don't forget to pass your old search context to
  3186.  * it, so it can reuse it and especially reuse the list of already visited
  3187.  * directories. If you want to delete the list of already visited directories
  3188.  * simply call vim_findfile_free_visited().
  3189.  *
  3190.  * When you are done call vim_findfile_cleanup() to free the search context.
  3191.  *
  3192.  * The function vim_findfile_init() has a long comment, which describes the
  3193.  * needed parameters.
  3194.  *
  3195.  *
  3196.  *
  3197.  * ATTENTION:
  3198.  * ==========
  3199.  *    Also we use an allocated search context here, this functions ARE NOT
  3200.  *    thread-safe!!!!!
  3201.  *
  3202.  *    To minimize parameter passing (or because I'm to lazy), only the
  3203.  *    external visible functions get a search context as a parameter. This is
  3204.  *    then assigned to a static global, which is used throughout the local
  3205.  *    functions.
  3206.  */
  3207.  
  3208. /*
  3209.  * type for the directory search stack
  3210.  */
  3211. typedef struct ff_stack
  3212. {
  3213.     struct ff_stack    *ffs_prev;
  3214.  
  3215.     /* the fix part (no wildcards) and the part containing the wildcards
  3216.      * of the search path
  3217.      */
  3218.     char_u        *ffs_fix_path;
  3219. #ifdef FEAT_PATH_EXTRA
  3220.     char_u        *ffs_wc_path;
  3221. #endif
  3222.  
  3223.     /* files/dirs found in the above directory, matched by the first wildcard
  3224.      * of wc_part
  3225.      */
  3226.     char_u        **ffs_filearray;
  3227.     int            ffs_filearray_size;
  3228.     char_u        ffs_filearray_cur;   /* needed for partly handled dirs */
  3229.  
  3230.     /* to store status of partly handled directories
  3231.      * 0: we work the on this directory for the first time
  3232.      * 1: this directory was partly searched in an earlier step
  3233.     */
  3234.     int            ffs_stage;
  3235.  
  3236.     /* How deep are we in the directory tree?
  3237.      * Counts backward from value of level parameter to vim_findfile_init
  3238.      */
  3239.     int            ffs_level;
  3240.  
  3241.     /* Did we already expand '**' to an empty string? */
  3242.     int            ffs_star_star_empty;
  3243. } ff_stack_T;
  3244.  
  3245. /*
  3246.  * type for already visited directories or files.
  3247.  */
  3248. typedef struct ff_visited
  3249. {
  3250.     struct ff_visited    *ffv_next;
  3251.  
  3252. #ifdef FEAT_PATH_EXTRA
  3253.     /* Visited directories are different if the wildcard string are
  3254.      * different. So we have to save it.
  3255.      */
  3256.     char_u        *ffv_wc_path;
  3257. #endif
  3258.     /* for unix use inode etc for comparison (needed because of links), else
  3259.      * use filename.
  3260.      */
  3261. #ifdef UNIX
  3262.     int            ffv_dev;    /* device number (-1 if not set) */
  3263.     ino_t        ffv_ino;    /* inode number */
  3264. #endif
  3265.     /* The memory for this struct is allocated according to the length of
  3266.      * ffv_fname.
  3267.      */
  3268.     char_u        ffv_fname[1];    /* actually longer */
  3269. } ff_visited_T;
  3270.  
  3271. /*
  3272.  * We might have to manage several visited lists during a search.
  3273.  * This is expecially needed for * the tags option. If tags is set to:
  3274.  *      "./++/tags,./++/TAGS,++/tags"  (replace + with *)
  3275.  * So we have to do 3 searches:
  3276.  *   1) search from the current files directory downward for the file "tags"
  3277.  *   2) search from the current files directory downward for the file "TAGS"
  3278.  *   3) search from Vims current directory downwards for the file "tags"
  3279.  * As you can see, the first and the third search are for the same file, so for
  3280.  * the third search we can use the visited list of the first search. For the
  3281.  * second search we must start from a empty visited list.
  3282.  * The struct ff_visited_list_hdr is used to manage a linked list of already
  3283.  * visited lists.
  3284.  */
  3285. typedef struct ff_visited_list_hdr
  3286. {
  3287.     struct ff_visited_list_hdr    *ffvl_next;
  3288.  
  3289.     /* the filename the attached visited list is for */
  3290.     char_u            *ffvl_filename;
  3291.  
  3292.     ff_visited_T        *ffvl_visited_list;
  3293.  
  3294. } ff_visited_list_hdr_T;
  3295.  
  3296.  
  3297. /*
  3298.  * '**' can be expanded to several directory levels.
  3299.  * Set the default maximium depth.
  3300.  */
  3301. #define FF_MAX_STAR_STAR_EXPAND ((char_u)30)
  3302. /*
  3303.  * The search context:
  3304.  *   ffsc_stack_ptr:    the stack for the dirs to search
  3305.  *   ffsc_visited_list: the currently active visited list
  3306.  *   ffsc_visited_lists_list: the list of all visited lists
  3307.  *   ffsc_file_to_search:     the file to search for
  3308.  *   ffsc_start_dir:    the starting directory, if search path was relative
  3309.  *   ffsc_fix_path:    the fix part of the given path (without wildcards)
  3310.  *            Needed for upward search.
  3311.  *   ffsc_wc_path:    the part of the given path containing wildcards
  3312.  *   ffsc_level:    how many levels of dirs to search downwards
  3313.  *   ffsc_stopdirs_v:    array of stop directories for upward search
  3314.  *   ffsc_need_dir:    TRUE if we search for a directory
  3315.  */
  3316. typedef struct ff_search_ctx_T
  3317. {
  3318.      ff_stack_T            *ffsc_stack_ptr;
  3319.      ff_visited_list_hdr_T    *ffsc_visited_list;
  3320.      ff_visited_list_hdr_T    *ffsc_visited_lists_list;
  3321.      char_u            *ffsc_file_to_search;
  3322.      char_u            *ffsc_start_dir;
  3323.      char_u            *ffsc_fix_path;
  3324. #ifdef FEAT_PATH_EXTRA
  3325.      char_u            *ffsc_wc_path;
  3326.      int            ffsc_level;
  3327.      char_u            **ffsc_stopdirs_v;
  3328. #endif
  3329.      int            ffsc_need_dir;
  3330. }ff_search_ctx_T;
  3331. static ff_search_ctx_T *ff_search_ctx = NULL;
  3332.  
  3333. /* used for expanding filenames */
  3334. static char_u        *ff_expand_buffer = NULL;
  3335.  
  3336. /* locally needed functions */
  3337. #ifdef FEAT_PATH_EXTRA
  3338. static int ff_check_visited __ARGS((ff_visited_T **, char_u *, char_u *));
  3339. #else
  3340. static int ff_check_visited __ARGS((ff_visited_T **, char_u *));
  3341. #endif
  3342. static void ff_free_visited_list __ARGS((ff_visited_T *vl));
  3343. static ff_visited_list_hdr_T* ff_get_visited_list __ARGS((char_u *));
  3344. #ifdef FEAT_PATH_EXTRA
  3345. static int ff_wc_equal __ARGS((char_u *s1, char_u *s2));
  3346. #endif
  3347.  
  3348. static void ff_push __ARGS((ff_stack_T *));
  3349. static ff_stack_T * ff_pop __ARGS((void));
  3350. static void ff_clear __ARGS((void));
  3351. static void ff_free_stack_element __ARGS((ff_stack_T *));
  3352. #ifdef FEAT_PATH_EXTRA
  3353. static ff_stack_T *ff_create_stack_element __ARGS((char_u *, char_u *, int, int));
  3354. #else
  3355. static ff_stack_T *ff_create_stack_element __ARGS((char_u *, int, int));
  3356. #endif
  3357. #ifdef FEAT_PATH_EXTRA
  3358. static int ff_path_in_stoplist __ARGS((char_u *, int, char_u **));
  3359. #endif
  3360.  
  3361. #ifdef FEAT_SEARCHPATH
  3362. static char_u *find_file_in_path_option __ARGS((char_u *ptr, int len, int options, int first, char_u *path_option, int need_dir, char_u *rel_fname));
  3363. #endif
  3364.  
  3365. #if 0
  3366. /*
  3367.  * if someone likes findfirst/findnext, here are the functions
  3368.  * NOT TESTED!!
  3369.  */
  3370.  
  3371. static void *ff_fn_search_context = NULL;
  3372.  
  3373.     char_u *
  3374. vim_findfirst(path, filename, level)
  3375.     char_u    *path;
  3376.     char_u    *filename;
  3377.     int        level;
  3378. {
  3379.     ff_fn_search_context =
  3380.     vim_findfile_init(path, filename, NULL, level, TRUE, FALSE,
  3381.         ff_fn_search_context, rel_fname);
  3382.     if (NULL == ff_fn_search_context)
  3383.     return NULL;
  3384.     else
  3385.     return vim_findnext()
  3386. }
  3387.  
  3388.     char_u *
  3389. vim_findnext()
  3390. {
  3391.     char_u *ret = vim_findfile(ff_fn_search_context);
  3392.  
  3393.     if (NULL == ret)
  3394.     {
  3395.     vim_findfile_cleanup(ff_fn_search_context);
  3396.     ff_fn_search_context = NULL;
  3397.     }
  3398.     return ret;
  3399. }
  3400. #endif
  3401.  
  3402. /*
  3403.  * Initialization routine for vim_findfile.
  3404.  *
  3405.  * Returns the newly allocated search context or NULL if an error occured.
  3406.  *
  3407.  * Don't forget to clean up by calling vim_findfile_cleanup() if you are done
  3408.  * with the search context.
  3409.  *
  3410.  * Find the file 'filename' in the directory 'path'.
  3411.  * The parameter 'path' may contain wildcards. If so only search 'level'
  3412.  * directories deep. The parameter 'level' is the absolute maximum and is
  3413.  * not related to restricts given to the '**' wildcard. If 'level' is 100
  3414.  * and you use '**200' vim_findfile() will stop after 100 levels.
  3415.  *
  3416.  * If 'stopdirs' is not NULL and nothing is found downward, the search is
  3417.  * restarted on the next higher directory level. This is repeated until the
  3418.  * start-directory of a search is contained in 'stopdirs'. 'stopdirs' has the
  3419.  * format ";*<dirname>*\(;<dirname>\)*;\=$".
  3420.  *
  3421.  * If the 'path' is relative, the starting dir for the search is either VIM's
  3422.  * current dir or if the path starts with "./" the current files dir.
  3423.  * If the 'path' is absolut, the starting dir is that part of the path before
  3424.  * the first wildcard.
  3425.  *
  3426.  * Upward search is only done on the starting dir.
  3427.  *
  3428.  * If 'free_visited' is TRUE the list of already visited files/directories is
  3429.  * cleared. Set this to FALSE if you just want to search from another
  3430.  * directory, but want to be sure that no directory from a previous search is
  3431.  * searched again. This is useful if you search for a file at different places.
  3432.  * The list of visited files/dirs can also be cleared with the function
  3433.  * vim_findfile_free_visited().
  3434.  *
  3435.  * Set the parameter 'need_dir' to TRUE if you want to search for a directory
  3436.  * instead of a file.
  3437.  *
  3438.  * A search context returned by a previous call to vim_findfile_init() can be
  3439.  * passed in the parameter 'search_ctx'. This context is than reused and
  3440.  * reinitialized with the new parameters. The list of already viseted
  3441.  * directories from this context is only deleted if the parameter
  3442.  * 'free_visited' is true. Be aware that the passed search_context is freed if
  3443.  * the reinitialization fails.
  3444.  *
  3445.  * If you don't have a search context from a previous call 'search_ctx' must be
  3446.  * NULL.
  3447.  *
  3448.  * This function silently ignores a few errors, vim_findfile() will have
  3449.  * limited functionality then.
  3450.  */
  3451. /*ARGSUSED*/
  3452.     void *
  3453. vim_findfile_init(path, filename, stopdirs, level, free_visited, need_dir,
  3454.                         search_ctx, tagfile, rel_fname)
  3455.     char_u    *path;
  3456.     char_u    *filename;
  3457.     char_u    *stopdirs;
  3458.     int        level;
  3459.     int        free_visited;
  3460.     int        need_dir;
  3461.     void    *search_ctx;
  3462.     int        tagfile;
  3463.     char_u    *rel_fname;    /* file name to use for "." */
  3464. {
  3465. #ifdef FEAT_PATH_EXTRA
  3466.     char_u    *wc_part;
  3467. #endif
  3468.     ff_stack_T    *sptr;
  3469.  
  3470.     /* If a search context is given by the caller, reuse it, else allocate a
  3471.      * new one.
  3472.      */
  3473.     if (search_ctx != NULL)
  3474.     ff_search_ctx = search_ctx;
  3475.     else
  3476.     {
  3477.     ff_search_ctx = (ff_search_ctx_T*)alloc(
  3478.                        (unsigned)sizeof(ff_search_ctx_T));
  3479.     if (ff_search_ctx == NULL)
  3480.         goto error_return;
  3481.     memset(ff_search_ctx, 0, sizeof(ff_search_ctx_T));
  3482.     }
  3483.  
  3484.     /* clear the search context, but NOT the visited lists */
  3485.     ff_clear();
  3486.  
  3487.     /* clear visited list if wanted */
  3488.     if (free_visited == TRUE)
  3489.     vim_findfile_free_visited(ff_search_ctx);
  3490.     else
  3491.     {
  3492.     /* Reuse old visited lists. Get the visited list for the given
  3493.      * filename. If no list for the current filename exists, creates a new
  3494.      * one.
  3495.      */
  3496.     ff_search_ctx->ffsc_visited_list = ff_get_visited_list(filename);
  3497.     if (ff_search_ctx->ffsc_visited_list == NULL)
  3498.         goto error_return;
  3499.     }
  3500.  
  3501.     if (ff_expand_buffer == NULL)
  3502.     {
  3503.     ff_expand_buffer = (char_u*)alloc(MAXPATHL);
  3504.     if (ff_expand_buffer == NULL)
  3505.         goto error_return;
  3506.     }
  3507.  
  3508.     /* Store information on starting dir now if path is relative.
  3509.      * If path is absolute, we do that later.
  3510.      */
  3511.     if (path[0] == '.'
  3512.         && (vim_ispathsep(path[1]) || path[1] == NUL)
  3513.         && (!tagfile || vim_strchr(p_cpo, CPO_DOTTAG) == NULL)
  3514.         && rel_fname != NULL)
  3515.     {
  3516.     int    len = (int)(gettail(rel_fname) - rel_fname);
  3517.  
  3518.     if (!vim_isAbsName(rel_fname) && len + 1 < MAXPATHL)
  3519.     {
  3520.         /* Make the start dir an absolute path name. */
  3521.         STRNCPY(ff_expand_buffer, rel_fname, len);
  3522.         ff_expand_buffer[len] = NUL;
  3523.         ff_search_ctx->ffsc_start_dir = FullName_save(ff_expand_buffer,
  3524.                                        FALSE);
  3525.     }
  3526.     else
  3527.         ff_search_ctx->ffsc_start_dir = vim_strnsave(rel_fname, len);
  3528.     if (ff_search_ctx->ffsc_start_dir == NULL)
  3529.         goto error_return;
  3530.     if (*++path != NUL)
  3531.         ++path;
  3532.     }
  3533.     else if (*path == NUL || !vim_isAbsName(path))
  3534.     {
  3535.     if (mch_dirname(ff_expand_buffer, MAXPATHL) == OK)
  3536.         ff_search_ctx->ffsc_start_dir = vim_strsave(ff_expand_buffer);
  3537.  
  3538.     if (ff_search_ctx->ffsc_start_dir == NULL)
  3539.         goto error_return;
  3540.     }
  3541.  
  3542. #ifdef FEAT_PATH_EXTRA
  3543.     /*
  3544.      * If stopdirs are given, split them into an array of pointers.
  3545.      * If this fails (mem allocation), there is no upward search at all or a
  3546.      * stop directory is not recognized -> continue silently.
  3547.      * If stopdirs just contains a ";" or is empty,
  3548.      * ff_search_ctx->ffsc_stopdirs_v will only contain a  NULL pointer. This
  3549.      * is handled as unlimited upward search.  See function
  3550.      * ff_path_in_stoplist() for details.
  3551.      */
  3552.     if (stopdirs != NULL)
  3553.     {
  3554.     char_u    *walker = stopdirs;
  3555.     int    dircount;
  3556.  
  3557.     while (*walker == ';')
  3558.         walker++;
  3559.  
  3560.     dircount = 1;
  3561.     ff_search_ctx->ffsc_stopdirs_v =
  3562.         (char_u **)alloc((unsigned)sizeof(char_u *));
  3563.  
  3564.     if (ff_search_ctx->ffsc_stopdirs_v != NULL)
  3565.     {
  3566.         do
  3567.         {
  3568.         char_u    *helper;
  3569.         void    *ptr;
  3570.  
  3571.         helper = walker;
  3572.         ptr = vim_realloc(ff_search_ctx->ffsc_stopdirs_v,
  3573.                            dircount+1 * sizeof(char_u *));
  3574.         if (ptr)
  3575.             ff_search_ctx->ffsc_stopdirs_v = ptr;
  3576.         else
  3577.             /* ignore, keep what we have and continue */
  3578.             break;
  3579.         walker = vim_strchr(walker, ';');
  3580.         if (walker)
  3581.         {
  3582.             ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
  3583.             vim_strnsave(helper, (int)(walker - helper));
  3584.             walker++;
  3585.         }
  3586.         else
  3587.             /* this might be "", which means ascent till top
  3588.              * of directory tree.
  3589.              */
  3590.             ff_search_ctx->ffsc_stopdirs_v[dircount-1] =
  3591.             vim_strsave(helper);
  3592.  
  3593.         dircount++;
  3594.  
  3595.         } while (walker != NULL);
  3596.         ff_search_ctx->ffsc_stopdirs_v[dircount-1] = NULL;
  3597.     }
  3598.     }
  3599. #endif
  3600.  
  3601. #ifdef FEAT_PATH_EXTRA
  3602.     ff_search_ctx->ffsc_level = level;
  3603.  
  3604.     /* split into:
  3605.      *  -fix path
  3606.      *  -wildcard_stuff (might be NULL)
  3607.      */
  3608.     wc_part = vim_strchr(path, '*');
  3609.     if (wc_part != NULL)
  3610.     {
  3611.     int    llevel;
  3612.     int    len;
  3613.     char_u    *errpt;
  3614.  
  3615.     /* save the fix part of the path */
  3616.     ff_search_ctx->ffsc_fix_path = vim_strnsave(path,
  3617.                                (int)(wc_part - path));
  3618.  
  3619.     /*
  3620.      * copy wc_path and add restricts to the '**' wildcard.
  3621.      * The octett after a '**' is used as a (binary) counter.
  3622.      * So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
  3623.      * or '**76' is transposed to '**N'( 'N' is ASCII value 76).
  3624.      * For EBCDIC you get different character values.
  3625.      * If no restrict is given after '**' the default is used.
  3626.      * Due to this technic the path looks awful if you print it as a
  3627.      * string.
  3628.      */
  3629.     len = 0;
  3630.     while (*wc_part != NUL)
  3631.     {
  3632.         if (STRNCMP(wc_part, "**", 2) == 0)
  3633.         {
  3634.         ff_expand_buffer[len++] = *wc_part++;
  3635.         ff_expand_buffer[len++] = *wc_part++;
  3636.  
  3637.         llevel = strtol((char *)wc_part, (char **)&errpt, 10);
  3638.         if (errpt != wc_part && llevel > 0 && llevel < 255)
  3639.             ff_expand_buffer[len++] = llevel;
  3640.         else if (errpt != wc_part && llevel == 0)
  3641.             /* restrict is 0 -> remove already added '**' */
  3642.             len -= 2;
  3643.         else
  3644.             ff_expand_buffer[len++] = FF_MAX_STAR_STAR_EXPAND;
  3645.         wc_part = errpt;
  3646.         if (*wc_part != PATHSEP && *wc_part != NUL)
  3647.         {
  3648.             EMSG2(_("E343: Invalid path: '**[number]' must be at the end of the path or be followed by '%s'."), PATHSEPSTR);
  3649.             goto error_return;
  3650.         }
  3651.         }
  3652.         else
  3653.         ff_expand_buffer[len++] = *wc_part++;
  3654.     }
  3655.     ff_expand_buffer[len] = NUL;
  3656.     ff_search_ctx->ffsc_wc_path =
  3657.         vim_strsave(ff_expand_buffer);
  3658.  
  3659.     if (ff_search_ctx->ffsc_wc_path == NULL)
  3660.         goto error_return;
  3661.     }
  3662.     else
  3663. #endif
  3664.     ff_search_ctx->ffsc_fix_path = vim_strsave(path);
  3665.  
  3666.     if (ff_search_ctx->ffsc_start_dir == NULL)
  3667.     {
  3668.     /* store the fix part as startdir.
  3669.      * This is needed if the parameter path is fully qualified.
  3670.      */
  3671.     ff_search_ctx->ffsc_start_dir = vim_strsave(ff_search_ctx->ffsc_fix_path);
  3672.     if (ff_search_ctx->ffsc_start_dir)
  3673.         ff_search_ctx->ffsc_fix_path[0] = NUL;
  3674.     }
  3675.  
  3676.     /* create an absolute path */
  3677.     STRCPY(ff_expand_buffer, ff_search_ctx->ffsc_start_dir);
  3678.     add_pathsep(ff_expand_buffer);
  3679.     STRCAT(ff_expand_buffer, ff_search_ctx->ffsc_fix_path);
  3680.     add_pathsep(ff_expand_buffer);
  3681.  
  3682.     sptr = ff_create_stack_element(ff_expand_buffer,
  3683. #ifdef FEAT_PATH_EXTRA
  3684.         ff_search_ctx->ffsc_wc_path,
  3685. #endif
  3686.         level, 0);
  3687.  
  3688.     if (sptr == NULL)
  3689.     goto error_return;
  3690.  
  3691.     ff_push(sptr);
  3692.  
  3693.     ff_search_ctx->ffsc_file_to_search = vim_strsave(filename);
  3694.     if (ff_search_ctx->ffsc_file_to_search == NULL)
  3695.     goto error_return;
  3696.  
  3697.     return ff_search_ctx;
  3698.  
  3699. error_return:
  3700.     /*
  3701.      * We clear the search context now!
  3702.      * Even when the caller gave us a (perhaps valid) context we free it here,
  3703.      * as we might have already destroyed it.
  3704.      */
  3705.     vim_findfile_cleanup(ff_search_ctx);
  3706.     return NULL;
  3707. }
  3708.  
  3709. #if defined(FEAT_PATH_EXTRA) || defined(PROTO)
  3710. /*
  3711.  * Get the stopdir string.  Check that ';' is not escaped.
  3712.  */
  3713.     char_u *
  3714. vim_findfile_stopdir(buf)
  3715.     char_u    *buf;
  3716. {
  3717.     char_u    *r_ptr = buf;
  3718.  
  3719.     while (*r_ptr != NUL && *r_ptr != ';')
  3720.     {
  3721.     if (r_ptr[0] == '\\' && r_ptr[1] == ';')
  3722.     {
  3723.         /* overwrite the escape char,
  3724.          * use STRLEN(r_ptr) to move the trailing '\0'
  3725.          */
  3726.         mch_memmove(r_ptr, r_ptr + 1, STRLEN(r_ptr));
  3727.         r_ptr++;
  3728.     }
  3729.     r_ptr++;
  3730.     }
  3731.     if (*r_ptr == ';')
  3732.     {
  3733.     *r_ptr = 0;
  3734.     r_ptr++;
  3735.     }
  3736.     else if (*r_ptr == NUL)
  3737.     r_ptr = NULL;
  3738.     return r_ptr;
  3739. }
  3740. #endif
  3741.  
  3742. /* Clean up the given search context. Can handle a NULL pointer */
  3743.     void
  3744. vim_findfile_cleanup(ctx)
  3745.     void    *ctx;
  3746. {
  3747.     if (NULL == ctx)
  3748.     return;
  3749.  
  3750.     ff_search_ctx = ctx;
  3751.  
  3752.     vim_findfile_free_visited(ctx);
  3753.     ff_clear();
  3754.     vim_free(ctx);
  3755.     ff_search_ctx = NULL;
  3756. }
  3757.  
  3758. /*
  3759.  * Find a file in a search context.
  3760.  * The search context was created with vim_findfile_init() above.
  3761.  * Return a pointer to an allocated file name or NULL if nothing found.
  3762.  * To get all matching files call this function until you get NULL.
  3763.  *
  3764.  * If the passed search_context is NULL, it the returns NULL.
  3765.  *
  3766.  * The search algorithm is depth first. To change this replace the
  3767.  * stack with a list (don't forget to leave partly searched directories on the
  3768.  * top of the list).
  3769.  */
  3770.     char_u *
  3771. vim_findfile(search_ctx)
  3772.     void    *search_ctx;
  3773. {
  3774.     char_u    *file_path;
  3775. #ifdef FEAT_PATH_EXTRA
  3776.     char_u    *rest_of_wildcards;
  3777.     char_u    *path_end = NULL;
  3778. #endif
  3779.     ff_stack_T    *ctx;
  3780. #if defined(FEAT_SEARCHPATH) || defined(FEAT_PATH_EXTRA)
  3781.     int        len;
  3782. #endif
  3783.     int        i;
  3784.     char_u    *p;
  3785. #ifdef FEAT_SEARCHPATH
  3786.     char_u    *suf;
  3787. #endif
  3788.  
  3789.     if (search_ctx == NULL)
  3790.     return NULL;
  3791.  
  3792.     ff_search_ctx = (ff_search_ctx_T*)search_ctx;
  3793.  
  3794.     /*
  3795.      * filepath is used as buffer for various actions and as the storage to
  3796.      * return a found filename.
  3797.      */
  3798.     if ((file_path = alloc((int)MAXPATHL)) == NULL)
  3799.     return NULL;
  3800.  
  3801. #ifdef FEAT_PATH_EXTRA
  3802.     /* store the end of the start dir -- needed for upward search */
  3803.     if (ff_search_ctx->ffsc_start_dir != NULL)
  3804.     path_end = &ff_search_ctx->ffsc_start_dir[STRLEN(ff_search_ctx->ffsc_start_dir)];
  3805. #endif
  3806.  
  3807. #ifdef FEAT_PATH_EXTRA
  3808.     /* upward search loop */
  3809.     for (;;)
  3810.     {
  3811. #endif
  3812.     /* downward search loop */
  3813.     for (;;)
  3814.     {
  3815.         /* check if user user wants to stop the search*/
  3816.         ui_breakcheck();
  3817.         if (got_int)
  3818.         break;
  3819.  
  3820.         /* get directory to work on from stack */
  3821.         ctx = ff_pop();
  3822.         if (ctx == NULL)
  3823.         break;
  3824.  
  3825.         /*
  3826.          * TODO: decide if we leave this test in
  3827.          *
  3828.          * GOOD: don't search a directory(-tree) twice.
  3829.          * BAD:  - check linked list for every new directory entered.
  3830.          *       - check for double files also done below
  3831.          *
  3832.          * Here we check if we already searched this directory.
  3833.          * We already searched a directory if:
  3834.          * 1) The directory is the same.
  3835.          * 2) We would use the same wildcard string.
  3836.          *
  3837.          * Good if you have links on same directory via several ways
  3838.          *  or you have selfreferences in directories (e.g. SuSE Linux 6.3:
  3839.          *  /etc/rc.d/init.d is linked to /etc/rc.d -> endless loop)
  3840.          *
  3841.          * This check is only needed for directories we work on for the
  3842.          * first time (hence ctx->ff_filearray == NULL)
  3843.          */
  3844.         if (ctx->ffs_filearray == NULL
  3845.             && ff_check_visited(&ff_search_ctx->ffsc_visited_list
  3846.                               ->ffvl_visited_list,
  3847.             ctx->ffs_fix_path
  3848. #ifdef FEAT_PATH_EXTRA
  3849.             , ctx->ffs_wc_path
  3850. #endif
  3851.             ) == FAIL)
  3852.         {
  3853. #ifdef FF_VERBOSE
  3854.         if (p_verbose >= 5)
  3855.         {
  3856.             /* always scroll up, don't overwrite */
  3857.             msg_scroll = TRUE;
  3858.             smsg((char_u *)"Already Searched: %s (%s)",
  3859.                        ctx->ffs_fix_path, ctx->ffs_wc_path);
  3860.             /* don't overwrite this either */
  3861.             msg_puts((char_u *)"\n");
  3862.             cmdline_row = msg_row;
  3863.         }
  3864. #endif
  3865.         ff_free_stack_element(ctx);
  3866.         continue;
  3867.         }
  3868. #ifdef FF_VERBOSE
  3869.         else if (p_verbose >= 5)
  3870.         {
  3871.         /* always scroll up, don't overwrite */
  3872.         msg_scroll = TRUE;
  3873.         smsg((char_u *)"Searching: %s (%s)", ctx->ffs_fix_path,
  3874.             ctx->ffs_wc_path);
  3875.         /* don't overwrite this either */
  3876.         msg_puts((char_u *)"\n");
  3877.         cmdline_row = msg_row;
  3878.         }
  3879. #endif
  3880.  
  3881.         /* check depth */
  3882.         if (ctx->ffs_level <= 0)
  3883.         {
  3884.         ff_free_stack_element(ctx);
  3885.         continue;
  3886.         }
  3887.  
  3888.         file_path[0] = NUL;
  3889.  
  3890.         /*
  3891.          * If no filearray till now expand wildcards
  3892.          * The function expand_wildcards() can handle an array of paths
  3893.          * and all possible expands are returned in one array. We use this
  3894.          * to handle the expansion of '**' into an empty string.
  3895.          */
  3896.         if (ctx->ffs_filearray == NULL)
  3897.         {
  3898.         char_u *dirptrs[2];
  3899.  
  3900.         /* we use filepath to build the path expand_wildcards() should
  3901.          * expand.
  3902.          */
  3903.         dirptrs[0] = file_path;
  3904.         dirptrs[1] = NULL;
  3905.  
  3906.         /* if we have a start dir copy it in */
  3907.         if (!vim_isAbsName(ctx->ffs_fix_path)
  3908.             && ff_search_ctx->ffsc_start_dir)
  3909.         {
  3910.             STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
  3911.             add_pathsep(file_path);
  3912.         }
  3913.  
  3914.         /* append the fix part of the search path */
  3915.         STRCAT(file_path, ctx->ffs_fix_path);
  3916.         add_pathsep(file_path);
  3917.  
  3918. #ifdef FEAT_PATH_EXTRA
  3919.         rest_of_wildcards = ctx->ffs_wc_path;
  3920.         if (*rest_of_wildcards != NUL)
  3921.         {
  3922.             len = (int)STRLEN(file_path);
  3923.             if (STRNCMP(rest_of_wildcards, "**", 2) == 0)
  3924.             {
  3925.             /* pointer to the restrict byte
  3926.              * The restrict byte is not a character!
  3927.              */
  3928.             p = rest_of_wildcards + 2;
  3929.  
  3930.             if (*p > 0)
  3931.             {
  3932.                 (*p)--;
  3933.                 file_path[len++] = '*';
  3934.             }
  3935.  
  3936.             if (*p == 0)
  3937.             {
  3938.                 /* remove '**<numb> from wildcards */
  3939.                 mch_memmove(rest_of_wildcards,
  3940.                     rest_of_wildcards + 3,
  3941.                     STRLEN(rest_of_wildcards + 3) + 1);
  3942.             }
  3943.             else
  3944.                 rest_of_wildcards += 3;
  3945.  
  3946.             if (ctx->ffs_star_star_empty == 0)
  3947.             {
  3948.                 /* if not done before, expand '**' to empty */
  3949.                 ctx->ffs_star_star_empty = 1;
  3950.                 dirptrs[1] = ctx->ffs_fix_path;
  3951.             }
  3952.             }
  3953.  
  3954.             /*
  3955.              * Here we copy until the next path separator or the end of
  3956.              * the path. If we stop at a path separator, there is
  3957.              * still somthing else left. This is handled below by
  3958.              * pushing every directory returned from expand_wildcards()
  3959.              * on the stack again for further search.
  3960.              */
  3961.             while (*rest_of_wildcards
  3962.                 && !vim_ispathsep(*rest_of_wildcards))
  3963.             file_path[len++] = *rest_of_wildcards++;
  3964.  
  3965.             file_path[len] = NUL;
  3966.             if (vim_ispathsep(*rest_of_wildcards))
  3967.             rest_of_wildcards++;
  3968.         }
  3969. #endif
  3970.  
  3971.         /*
  3972.          * Expand wildcards like "*" and "$VAR".
  3973.          * If the path is a URL don't try this.
  3974.          */
  3975.         if (path_with_url(dirptrs[0]))
  3976.         {
  3977.             ctx->ffs_filearray = (char_u **)
  3978.                           alloc((unsigned)sizeof(char *));
  3979.             if (ctx->ffs_filearray != NULL
  3980.                 && (ctx->ffs_filearray[0]
  3981.                 = vim_strsave(dirptrs[0])) != NULL)
  3982.             ctx->ffs_filearray_size = 1;
  3983.             else
  3984.             ctx->ffs_filearray_size = 0;
  3985.         }
  3986.         else
  3987.             expand_wildcards((dirptrs[1] == NULL) ? 1 : 2, dirptrs,
  3988.                 &ctx->ffs_filearray_size,
  3989.                 &ctx->ffs_filearray,
  3990.                 EW_DIR|EW_ADDSLASH|EW_SILENT);
  3991.  
  3992.         ctx->ffs_filearray_cur = 0;
  3993.         ctx->ffs_stage = 0;
  3994.         }
  3995. #ifdef FEAT_PATH_EXTRA
  3996.         else
  3997.         rest_of_wildcards = &ctx->ffs_wc_path[STRLEN(ctx->ffs_wc_path)];
  3998. #endif
  3999.  
  4000.         if (ctx->ffs_stage == 0)
  4001.         {
  4002.         /* this is the first time we work on this directory */
  4003. #ifdef FEAT_PATH_EXTRA
  4004.         if (*rest_of_wildcards == NUL)
  4005. #endif
  4006.         {
  4007.             /*
  4008.              * we don't have further wildcards to expand, so we have to
  4009.              * check for the final file now
  4010.              */
  4011.             for (i = ctx->ffs_filearray_cur;
  4012.                          i < ctx->ffs_filearray_size; ++i)
  4013.             {
  4014.             if (!path_with_url(ctx->ffs_filearray[i])
  4015.                      && !mch_isdir(ctx->ffs_filearray[i]))
  4016.                 continue;   /* not a directory */
  4017.  
  4018.             /* prepare the filename to be checked for existance
  4019.              * below */
  4020.             STRCPY(file_path, ctx->ffs_filearray[i]);
  4021.             add_pathsep(file_path);
  4022.             STRCAT(file_path, ff_search_ctx->ffsc_file_to_search);
  4023.  
  4024.             /*
  4025.              * Try without extra suffix and then with suffixes
  4026.              * from 'suffixesadd'.
  4027.              */
  4028. #ifdef FEAT_SEARCHPATH
  4029.             len = (int)STRLEN(file_path);
  4030.             suf = curbuf->b_p_sua;
  4031.             for (;;)
  4032. #endif
  4033.             {
  4034.                 /* if file exists and we didn't already find it */
  4035.                 if ((path_with_url(file_path)
  4036.                     || (mch_getperm(file_path) >= 0
  4037.                         && (!ff_search_ctx->ffsc_need_dir
  4038.                         || mch_isdir(file_path))))
  4039. #ifndef FF_VERBOSE
  4040.                     && (ff_check_visited(
  4041.                         &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
  4042.                         file_path
  4043. #ifdef FEAT_PATH_EXTRA
  4044.                         , (char_u *)""
  4045. #endif
  4046.                         ) == OK)
  4047. #endif
  4048.                    )
  4049.                 {
  4050. #ifdef FF_VERBOSE
  4051.                 if (ff_check_visited(
  4052.                         &ff_search_ctx->ffsc_visited_list->ffvl_visited_list,
  4053.                         file_path
  4054. #ifdef FEAT_PATH_EXTRA
  4055.                         , (char_u *)""
  4056. #endif
  4057.                             ) == FAIL)
  4058.                 {
  4059.                     if (p_verbose >= 5)
  4060.                     {
  4061.                     /* always scroll up, don't overwrite */
  4062.                     msg_scroll = TRUE;
  4063.                     smsg((char_u *)"Already: %s", file_path);
  4064.                     /* don't overwrite this either */
  4065.                     msg_puts((char_u *)"\n");
  4066.                     cmdline_row = msg_row;
  4067.                     }
  4068.                     continue;
  4069.                 }
  4070. #endif
  4071.  
  4072.                 /* push dir to examine rest of subdirs later */
  4073.                 ctx->ffs_filearray_cur = i + 1;
  4074.                 ff_push(ctx);
  4075.  
  4076.                 simplify_filename(file_path);
  4077.                 if (mch_dirname(ff_expand_buffer, MAXPATHL)
  4078.                                     == OK)
  4079.                 {
  4080.                     p = shorten_fname(file_path,
  4081.                                 ff_expand_buffer);
  4082.                     if (p != NULL)
  4083.                     mch_memmove(file_path, p,
  4084.                                    STRLEN(p) + 1);
  4085.                 }
  4086. #ifdef FF_VERBOSE
  4087.                 if (p_verbose >= 5)
  4088.                 {
  4089.                     /* always scroll up, don't overwrite */
  4090.                     msg_scroll = TRUE;
  4091.                     smsg((char_u *)"HIT: %s", file_path);
  4092.                     /* don't overwrite this either */
  4093.                     msg_puts((char_u *)"\n");
  4094.                     cmdline_row = msg_row;
  4095.                 }
  4096. #endif
  4097.                 return file_path;
  4098.                 }
  4099.  
  4100. #ifdef FEAT_SEARCHPATH
  4101.                 /* Not found or found already, try next suffix. */
  4102.                 if (*suf == NUL)
  4103.                 break;
  4104.                 copy_option_part(&suf, file_path + len,
  4105.                              MAXPATHL - len, ",");
  4106. #endif
  4107.             }
  4108.             }
  4109.         }
  4110. #ifdef FEAT_PATH_EXTRA
  4111.         else
  4112.         {
  4113.             /*
  4114.              * still wildcards left, push the directories for further
  4115.              * search
  4116.              */
  4117.             for (i = ctx->ffs_filearray_cur; i < ctx->ffs_filearray_size;
  4118.                                       ++i)
  4119.             {
  4120.             if (!mch_isdir(ctx->ffs_filearray[i]))
  4121.                 continue;    /* not a directory */
  4122.  
  4123.             ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
  4124.                       rest_of_wildcards, ctx->ffs_level - 1, 0));
  4125.             }
  4126.         }
  4127. #endif
  4128.         ctx->ffs_filearray_cur = 0;
  4129.         ctx->ffs_stage = 1;
  4130.         }
  4131.  
  4132. #ifdef FEAT_PATH_EXTRA
  4133.         /*
  4134.          * if wildcards contains '**' we have to descent till we reach the
  4135.          * leaves of the directory tree.
  4136.          */
  4137.         if (STRNCMP(ctx->ffs_wc_path, "**", 2) == 0)
  4138.         {
  4139.         for (i = ctx->ffs_filearray_cur; i < ctx->ffs_filearray_size; ++i)
  4140.         {
  4141.             if (STRCMP(ctx->ffs_filearray[i], ctx->ffs_fix_path) == 0)
  4142.             continue; /* don't repush same directory */
  4143.             if (!mch_isdir(ctx->ffs_filearray[i]))
  4144.             continue;   /* not a directory */
  4145.             ff_push(ff_create_stack_element(ctx->ffs_filearray[i],
  4146.                 ctx->ffs_wc_path, ctx->ffs_level - 1, 1));
  4147.         }
  4148.         }
  4149. #endif
  4150.  
  4151.         /* we are done with the current directory */
  4152.         ff_free_stack_element(ctx);
  4153.  
  4154.     }
  4155.  
  4156. #ifdef FEAT_PATH_EXTRA
  4157.     /* If we reached this, we didn't find anything downwards.
  4158.      * Let's check if we should do an upward search.
  4159.      */
  4160.     if (ff_search_ctx->ffsc_start_dir
  4161.         && ff_search_ctx->ffsc_stopdirs_v != NULL && !got_int)
  4162.     {
  4163.         ff_stack_T  *sptr;
  4164.  
  4165.         /* is the last starting directory in the stop list? */
  4166.         if (ff_path_in_stoplist(ff_search_ctx->ffsc_start_dir,
  4167.                (int)(path_end - ff_search_ctx->ffsc_start_dir),
  4168.                ff_search_ctx->ffsc_stopdirs_v) == TRUE)
  4169.         break;
  4170.  
  4171.         /* cut of last dir */
  4172.         while (path_end > ff_search_ctx->ffsc_start_dir
  4173.             && *path_end == PATHSEP)
  4174.         path_end--;
  4175.         while (path_end > ff_search_ctx->ffsc_start_dir
  4176.             && *(path_end-1) != PATHSEP)
  4177.         path_end--;
  4178.         *path_end = 0;
  4179.         path_end--;
  4180.  
  4181.         if (*ff_search_ctx->ffsc_start_dir == 0)
  4182.         break;
  4183.  
  4184.         STRCPY(file_path, ff_search_ctx->ffsc_start_dir);
  4185.         add_pathsep(file_path);
  4186.         STRCAT(file_path, ff_search_ctx->ffsc_fix_path);
  4187.  
  4188.         /* create a new stack entry */
  4189.         sptr = ff_create_stack_element(file_path,
  4190.             ff_search_ctx->ffsc_wc_path, ff_search_ctx->ffsc_level, 0);
  4191.         if (sptr == NULL)
  4192.         break;
  4193.         ff_push(sptr);
  4194.     }
  4195.     else
  4196.         break;
  4197.     }
  4198. #endif
  4199.  
  4200.     vim_free(file_path);
  4201.     return NULL;
  4202. }
  4203.  
  4204. /*
  4205.  * Free the list of lists of visited files and directories
  4206.  * Can handle it if the passed search_context is NULL;
  4207.  */
  4208.     void
  4209. vim_findfile_free_visited(search_ctx)
  4210.     void    *search_ctx;
  4211. {
  4212.     ff_visited_list_hdr_T *vp;
  4213.  
  4214.     if (NULL == search_ctx)
  4215.     return;
  4216.  
  4217.     ff_search_ctx = (ff_search_ctx_T*)search_ctx;
  4218.  
  4219.     while (NULL != ff_search_ctx->ffsc_visited_lists_list)
  4220.     {
  4221.     vp = ff_search_ctx->ffsc_visited_lists_list->ffvl_next;
  4222.     ff_free_visited_list(
  4223.         ff_search_ctx->ffsc_visited_lists_list->ffvl_visited_list);
  4224.  
  4225.     vim_free(ff_search_ctx->ffsc_visited_lists_list->ffvl_filename);
  4226.     vim_free(ff_search_ctx->ffsc_visited_lists_list);
  4227.     ff_search_ctx->ffsc_visited_lists_list = vp;
  4228.     }
  4229.     ff_search_ctx->ffsc_visited_lists_list = NULL;
  4230. }
  4231.  
  4232.     static void
  4233. ff_free_visited_list(vl)
  4234.     ff_visited_T *vl;
  4235. {
  4236.     ff_visited_T *vp;
  4237.  
  4238.     while (vl != NULL)
  4239.     {
  4240.     vp = vl->ffv_next;
  4241.     vim_free(vl);
  4242.     vl = vp;
  4243.     }
  4244.     vl = NULL;
  4245. }
  4246.  
  4247. /*
  4248.  * Returns the already visited list for the given filename. If none is found it
  4249.  * allocates a new one.
  4250.  */
  4251.     static ff_visited_list_hdr_T*
  4252. ff_get_visited_list(filename)
  4253.     char_u    *filename;
  4254. {
  4255.     ff_visited_list_hdr_T  *retptr = NULL;
  4256.  
  4257.     /* check if a visited list for the given filename exists */
  4258.     if (ff_search_ctx->ffsc_visited_lists_list!= NULL)
  4259.     {
  4260.     retptr = ff_search_ctx->ffsc_visited_lists_list;
  4261.     while (retptr != NULL)
  4262.     {
  4263.         if (0 == STRCMP(filename, retptr->ffvl_filename))
  4264.         {
  4265. #ifdef FF_VERBOSE
  4266.         if (p_verbose >= 5)
  4267.         {
  4268.             /* always scroll up, don't overwrite */
  4269.             msg_scroll = TRUE;
  4270.             smsg((char_u *)"ff_get_visited_list: FOUND list for %s",
  4271.                 filename);
  4272.             /* don't overwrite this either */
  4273.             msg_puts((char_u *)"\n");
  4274.             cmdline_row = msg_row;
  4275.         }
  4276. #endif
  4277.         return retptr;
  4278.         }
  4279.         retptr = retptr->ffvl_next;
  4280.     }
  4281.     }
  4282.  
  4283. #ifdef FF_VERBOSE
  4284.     if (p_verbose >= 5)
  4285.     {
  4286.     /* always scroll up, don't overwrite */
  4287.     msg_scroll = TRUE;
  4288.     smsg((char_u *)"ff_get_visited_list: new list for %s",
  4289.         filename);
  4290.     /* don't overwrite this either */
  4291.     msg_puts((char_u *)"\n");
  4292.     cmdline_row = msg_row;
  4293.     }
  4294. #endif
  4295.  
  4296.     /*
  4297.      * if we reach this we didn't find a list and we have to allocate new list
  4298.      */
  4299.     retptr = (ff_visited_list_hdr_T*)alloc((unsigned)sizeof(*retptr));
  4300.     if (retptr == NULL)
  4301.     return NULL;
  4302.  
  4303.     retptr->ffvl_visited_list = NULL;
  4304.     retptr->ffvl_filename = vim_strsave(filename);
  4305.     if (retptr->ffvl_filename == NULL)
  4306.     {
  4307.     vim_free(retptr);
  4308.     return NULL;
  4309.     }
  4310.     retptr->ffvl_next = ff_search_ctx->ffsc_visited_lists_list;
  4311.     ff_search_ctx->ffsc_visited_lists_list = retptr;
  4312.  
  4313.     return retptr;
  4314. }
  4315.  
  4316. #ifdef FEAT_PATH_EXTRA
  4317. /*
  4318.  * check if two wildcard pathes are equal. Returns TRUE or FALSE.
  4319.  * They are equal if:
  4320.  *  - both pathes are NULL
  4321.  *  - they have the same length
  4322.  *  - char by char comparison is OK
  4323.  *  - the only differences are in the counters behind a '**', so
  4324.  *    '**\20' is equal to '**\24'
  4325.  */
  4326.     static int
  4327. ff_wc_equal(s1, s2)
  4328.     char_u    *s1;
  4329.     char_u    *s2;
  4330. {
  4331.     int        i;
  4332.  
  4333.     if (s1 == s2)
  4334.     return TRUE;
  4335.  
  4336.     if (s1 == NULL || s2 == NULL)
  4337.     return FALSE;
  4338.  
  4339.     if (STRLEN(s1) != STRLEN(s2))
  4340.     return FAIL;
  4341.  
  4342.     for (i = 0; s1[i] != NUL && s2[i] != NUL; i++)
  4343.     {
  4344.     if (s1[i] != s2[i])
  4345.     {
  4346.         if (i >= 2)
  4347.         if (s1[i-1] == '*' && s1[i-2] == '*')
  4348.             continue;
  4349.         else
  4350.             return FAIL;
  4351.         else
  4352.         return FAIL;
  4353.     }
  4354.     }
  4355.     return TRUE;
  4356. }
  4357. #endif
  4358.  
  4359. /*
  4360.  * maintains the list of already visited files and dirs
  4361.  * returns FAIL if the given file/dir is already in the list
  4362.  * returns OK if it is newly added
  4363.  *
  4364.  * TODO: What to do on memory allocation problems?
  4365.  *     -> return TRUE - Better the file is found several times instead of
  4366.  *        never.
  4367.  */
  4368.     static int
  4369. ff_check_visited(visited_list, fname
  4370. #ifdef FEAT_PATH_EXTRA
  4371.     , wc_path
  4372. #endif
  4373.     )
  4374.     ff_visited_T    **visited_list;
  4375.     char_u        *fname;
  4376. #ifdef FEAT_PATH_EXTRA
  4377.     char_u        *wc_path;
  4378. #endif
  4379. {
  4380.     ff_visited_T    *vp;
  4381. #ifdef UNIX
  4382.     struct stat        st;
  4383.     int            url = FALSE;
  4384. #endif
  4385.  
  4386.     /* For an URL we only compare the name, otherwise we compare the
  4387.      * device/inode (unix) or the full path name (not Unix). */
  4388.     if (path_with_url(fname))
  4389.     {
  4390.     STRNCPY(ff_expand_buffer, fname, MAXPATHL);
  4391. #ifdef UNIX
  4392.     url = TRUE;
  4393. #endif
  4394.     }
  4395.     else
  4396.     {
  4397.     ff_expand_buffer[0] = NUL;
  4398. #ifdef UNIX
  4399.     if (mch_stat((char *)fname, &st) < 0)
  4400. #else
  4401.     if (vim_FullName(fname, ff_expand_buffer, MAXPATHL, TRUE) == FAIL)
  4402. #endif
  4403.         return FAIL;
  4404.     }
  4405.  
  4406.     /* check against list of already visited files */
  4407.     for (vp = *visited_list; vp != NULL; vp = vp->ffv_next)
  4408.     {
  4409.     if (
  4410. #ifdef UNIX
  4411.         !url
  4412.             ? (vp->ffv_dev == st.st_dev
  4413.             && vp->ffv_ino == st.st_ino)
  4414.             :
  4415. #endif
  4416.         fnamecmp(vp->ffv_fname, ff_expand_buffer) == 0
  4417.        )
  4418.     {
  4419. #ifdef FEAT_PATH_EXTRA
  4420.         /* are the wildcard parts equal */
  4421.         if (ff_wc_equal(vp->ffv_wc_path, wc_path) == TRUE)
  4422. #endif
  4423.         /* already visited */
  4424.         return FAIL;
  4425.     }
  4426.     }
  4427.  
  4428.     /*
  4429.      * New file/dir.  Add it to the list of visited files/dirs.
  4430.      */
  4431.     vp = (ff_visited_T *)alloc((unsigned)(sizeof(ff_visited_T)
  4432.                          + STRLEN(ff_expand_buffer)));
  4433.  
  4434.     if (vp != NULL)
  4435.     {
  4436. #ifdef UNIX
  4437.     if (!url)
  4438.     {
  4439.         vp->ffv_ino = st.st_ino;
  4440.         vp->ffv_dev = st.st_dev;
  4441.         vp->ffv_fname[0] = NUL;
  4442.     }
  4443.     else
  4444.     {
  4445.         vp->ffv_ino = 0;
  4446.         vp->ffv_dev = -1;
  4447. #endif
  4448.         STRCPY(vp->ffv_fname, ff_expand_buffer);
  4449. #ifdef UNIX
  4450.     }
  4451. #endif
  4452. #ifdef FEAT_PATH_EXTRA
  4453.     if (wc_path != NULL)
  4454.         vp->ffv_wc_path = vim_strsave(wc_path);
  4455.     else
  4456.         vp->ffv_wc_path = NULL;
  4457. #endif
  4458.  
  4459.     vp->ffv_next = *visited_list;
  4460.     *visited_list = vp;
  4461.     }
  4462.  
  4463.     return OK;
  4464. }
  4465.  
  4466. /*
  4467.  * create stack element from given path pieces
  4468.  */
  4469.     static ff_stack_T *
  4470. ff_create_stack_element(fix_part,
  4471. #ifdef FEAT_PATH_EXTRA
  4472.     wc_part,
  4473. #endif
  4474.     level, star_star_empty)
  4475.     char_u    *fix_part;
  4476. #ifdef FEAT_PATH_EXTRA
  4477.     char_u    *wc_part;
  4478. #endif
  4479.     int        level;
  4480.     int        star_star_empty;
  4481. {
  4482.     ff_stack_T    *new;
  4483.  
  4484.     new = (ff_stack_T *)alloc((unsigned)sizeof(ff_stack_T));
  4485.     if (new == NULL)
  4486.     return NULL;
  4487.  
  4488.     new->ffs_prev       = NULL;
  4489.     new->ffs_filearray       = NULL;
  4490.     new->ffs_filearray_size = 0;
  4491.     new->ffs_filearray_cur  = 0;
  4492.     new->ffs_stage       = 0;
  4493.     new->ffs_level       = level;
  4494.     new->ffs_star_star_empty = star_star_empty;;
  4495.  
  4496.     /* the following saves NULL pointer checks in vim_findfile */
  4497.     if (fix_part == NULL)
  4498.     fix_part = (char_u *)"";
  4499.     new->ffs_fix_path = vim_strsave(fix_part);
  4500.  
  4501. #ifdef FEAT_PATH_EXTRA
  4502.     if (wc_part == NULL)
  4503.     wc_part  = (char_u *)"";
  4504.     new->ffs_wc_path = vim_strsave(wc_part);
  4505. #endif
  4506.  
  4507.     if (new->ffs_fix_path == NULL
  4508. #ifdef FEAT_PATH_EXTRA
  4509.         || new->ffs_wc_path == NULL
  4510. #endif
  4511.         )
  4512.     {
  4513.     ff_free_stack_element(new);
  4514.     new = NULL;
  4515.     }
  4516.  
  4517.     return new;
  4518. }
  4519.  
  4520. /*
  4521.  * push a dir on the directory stack
  4522.  */
  4523.     static void
  4524. ff_push(ctx)
  4525.     ff_stack_T *ctx;
  4526. {
  4527.     /* check for NULL pointer, not to return an error to the user, but
  4528.      * to prevent a crash
  4529.      */
  4530.     if (ctx != NULL)
  4531.     {
  4532.     ctx->ffs_prev   = ff_search_ctx->ffsc_stack_ptr;
  4533.     ff_search_ctx->ffsc_stack_ptr = ctx;
  4534.     }
  4535. }
  4536.  
  4537. /*
  4538.  * pop a dir from the directory stack
  4539.  * returns NULL if stack is empty
  4540.  */
  4541.     static ff_stack_T *
  4542. ff_pop()
  4543. {
  4544.     ff_stack_T  *sptr;
  4545.  
  4546.     sptr = ff_search_ctx->ffsc_stack_ptr;
  4547.     if (ff_search_ctx->ffsc_stack_ptr != NULL)
  4548.     ff_search_ctx->ffsc_stack_ptr = ff_search_ctx->ffsc_stack_ptr->ffs_prev;
  4549.  
  4550.     return sptr;
  4551. }
  4552.  
  4553. /*
  4554.  * free the given stack element
  4555.  */
  4556.     static void
  4557. ff_free_stack_element(ctx)
  4558.     ff_stack_T  *ctx;
  4559. {
  4560.     /* vim_free handles possible NULL pointers */
  4561.     vim_free(ctx->ffs_fix_path);
  4562. #ifdef FEAT_PATH_EXTRA
  4563.     vim_free(ctx->ffs_wc_path);
  4564. #endif
  4565.  
  4566.     if (ctx->ffs_filearray != NULL)
  4567.     FreeWild(ctx->ffs_filearray_size, ctx->ffs_filearray);
  4568.  
  4569.     vim_free(ctx);
  4570. }
  4571.  
  4572. /*
  4573.  * clear the search context
  4574.  */
  4575.     static void
  4576. ff_clear()
  4577. {
  4578.     ff_stack_T   *sptr;
  4579.  
  4580.     /* clear up stack */
  4581.     while ((sptr = ff_pop()) != NULL)
  4582.     ff_free_stack_element(sptr);
  4583.  
  4584.     vim_free(ff_search_ctx->ffsc_file_to_search);
  4585.     vim_free(ff_search_ctx->ffsc_start_dir);
  4586.     vim_free(ff_search_ctx->ffsc_fix_path);
  4587. #ifdef FEAT_PATH_EXTRA
  4588.     vim_free(ff_search_ctx->ffsc_wc_path);
  4589. #endif
  4590.  
  4591. #ifdef FEAT_PATH_EXTRA
  4592.     if (ff_search_ctx->ffsc_stopdirs_v != NULL)
  4593.     {
  4594.     int  i = 0;
  4595.  
  4596.     while (ff_search_ctx->ffsc_stopdirs_v[i] != NULL)
  4597.     {
  4598.         vim_free(ff_search_ctx->ffsc_stopdirs_v[i]);
  4599.         i++;
  4600.     }
  4601.     vim_free(ff_search_ctx->ffsc_stopdirs_v);
  4602.     }
  4603.     ff_search_ctx->ffsc_stopdirs_v = NULL;
  4604. #endif
  4605.  
  4606.     /* reset everything */
  4607.     ff_search_ctx->ffsc_file_to_search    = NULL;
  4608.     ff_search_ctx->ffsc_start_dir    = NULL;
  4609.     ff_search_ctx->ffsc_fix_path    = NULL;
  4610. #ifdef FEAT_PATH_EXTRA
  4611.     ff_search_ctx->ffsc_wc_path        = NULL;
  4612.     ff_search_ctx->ffsc_level        = 0;
  4613. #endif
  4614. }
  4615.  
  4616. #ifdef FEAT_PATH_EXTRA
  4617. /*
  4618.  * check if the given path is in the stopdirs
  4619.  * returns TRUE if yes else FALSE
  4620.  */
  4621.     static int
  4622. ff_path_in_stoplist(path, path_len, stopdirs_v)
  4623.     char_u    *path;
  4624.     int        path_len;
  4625.     char_u    **stopdirs_v;
  4626. {
  4627.     int        i = 0;
  4628.  
  4629.     /* eat up trailing path separators, except the first */
  4630.     while (path_len > 1 && path[path_len - 1] == PATHSEP)
  4631.     path_len--;
  4632.  
  4633.     /* if no path consider it as match */
  4634.     if (path_len == 0)
  4635.     return TRUE;
  4636.  
  4637.     for (i = 0; stopdirs_v[i] != NULL; i++)
  4638.     {
  4639.     if ((int)STRLEN(stopdirs_v[i]) > path_len)
  4640.     {
  4641.         /* match for parent directory. So '/home' also matches
  4642.          * '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
  4643.          * '/home/r' would also match '/home/rks'
  4644.          */
  4645.         if (STRNCMP(stopdirs_v[i], path, path_len) == 0
  4646.             && stopdirs_v[i][path_len] == PATHSEP)
  4647.         return TRUE;
  4648.     }
  4649.     else
  4650.     {
  4651.         if (STRCMP(stopdirs_v[i], path) == 0)
  4652.         return TRUE;
  4653.     }
  4654.     }
  4655.     return FALSE;
  4656. }
  4657. #endif
  4658.  
  4659. #if defined(FEAT_SEARCHPATH) || defined(PROTO)
  4660. /*
  4661.  * Find the file name "ptr[len]" in the path.
  4662.  *
  4663.  * On the first call set the parameter 'first' to TRUE to initialize
  4664.  * the search.  For repeating calls to FALSE.
  4665.  *
  4666.  * Repeating calls will return other files called 'ptr[len]' from the path.
  4667.  *
  4668.  * Only on the first call 'ptr' and 'len' are used.  For repeating calls they
  4669.  * don't need valid values.
  4670.  *
  4671.  * If nothing found on the first call the option FNAME_MESS will issue the
  4672.  * message:
  4673.  *        'Can't find file "<file>" in path'
  4674.  * On repeating calls:
  4675.  *        'No more file "<file>" found in path'
  4676.  *
  4677.  * options:
  4678.  * FNAME_MESS        give error message when not found
  4679.  *
  4680.  * Uses NameBuff[]!
  4681.  *
  4682.  * Returns an allocated string for the file name.  NULL for error.
  4683.  *
  4684.  */
  4685.     char_u *
  4686. find_file_in_path(ptr, len, options, first, rel_fname)
  4687.     char_u    *ptr;        /* file name */
  4688.     int        len;        /* length of file name */
  4689.     int        options;
  4690.     int        first;        /* use count'th matching file name */
  4691.     char_u    *rel_fname;    /* file name searching relative to */
  4692. {
  4693.     return find_file_in_path_option(ptr, len, options, first,
  4694.         *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path,
  4695.         FALSE, rel_fname);
  4696. }
  4697.  
  4698. /*
  4699.  * Find the directory name "ptr[len]" in the path.
  4700.  *
  4701.  * options:
  4702.  * FNAME_MESS        give error message when not found
  4703.  *
  4704.  * Uses NameBuff[]!
  4705.  *
  4706.  * Returns an allocated string for the file name.  NULL for error.
  4707.  */
  4708.     char_u *
  4709. find_directory_in_path(ptr, len, options, rel_fname)
  4710.     char_u    *ptr;        /* file name */
  4711.     int        len;        /* length of file name */
  4712.     int        options;
  4713.     char_u    *rel_fname;    /* file name searching relative to */
  4714. {
  4715.     return find_file_in_path_option(ptr, len, options, TRUE, p_cdpath,
  4716.                                  TRUE, rel_fname);
  4717. }
  4718.  
  4719.     static char_u *
  4720. find_file_in_path_option(ptr, len, options, first, path_option, need_dir, rel_fname)
  4721.     char_u    *ptr;        /* file name */
  4722.     int        len;        /* length of file name */
  4723.     int        options;
  4724.     int        first;        /* use count'th matching file name */
  4725.     char_u    *path_option;    /* p_path or p_cdpath */
  4726.     int        need_dir;    /* looking for directory name */
  4727.     char_u    *rel_fname;    /* file name we are looking relative to. */
  4728. {
  4729.     static void        *search_ctx = NULL;
  4730.     static char_u    *dir;
  4731.     static char_u    *file_to_find = NULL;
  4732.     static int        did_findfile_init = FALSE;
  4733.     char_u        save_char;
  4734.     char_u        *file_name = NULL;
  4735.     char_u        *buf = NULL;
  4736.     int            rel_to_curdir;
  4737. #ifdef AMIGA
  4738.     struct Process    *proc = (struct Process *)FindTask(0L);
  4739.     APTR        save_winptr = proc->pr_WindowPtr;
  4740.  
  4741.     /* Avoid a requester here for a volume that doesn't exist. */
  4742.     proc->pr_WindowPtr = (APTR)-1L;
  4743. #endif
  4744.  
  4745.     if (first == TRUE)
  4746.     {
  4747.     /* copy file name into NameBuff, expanding environment variables */
  4748.     save_char = ptr[len];
  4749.     ptr[len] = NUL;
  4750.     expand_env(ptr, NameBuff, MAXPATHL);
  4751.     ptr[len] = save_char;
  4752.  
  4753.     vim_free(file_to_find);
  4754.     file_to_find = vim_strsave(NameBuff);
  4755.     if (file_to_find == NULL)    /* out of memory */
  4756.     {
  4757.         file_name = NULL;
  4758.         goto theend;
  4759.     }
  4760. #ifdef VMS
  4761.     if (vim_isAbsName(file_to_find))
  4762.         file_to_find = vms_fixfilename(file_to_find);
  4763. #endif
  4764.     }
  4765.  
  4766.     rel_to_curdir = (file_to_find[0] == '.'
  4767.             && (file_to_find[1] == NUL
  4768.             || vim_ispathsep(file_to_find[1])
  4769.             || (file_to_find[1] == '.'
  4770.                 && (file_to_find[2] == NUL
  4771.                 || vim_ispathsep(file_to_find[2])))));
  4772.     if (vim_isAbsName(file_to_find)
  4773.         /* "..", "../path", "." and "./path": don't use the path_option */
  4774.         || rel_to_curdir
  4775. #if defined(MSWIN) || defined(MSDOS) || defined(OS2)
  4776.         /* handle "\tmp" as absolute path */
  4777.         || vim_ispathsep(file_to_find[0])
  4778.         /* handle "c:name" as absulute path */
  4779.         || (file_to_find[0] != NUL && file_to_find[1] == ':')
  4780. #endif
  4781. #ifdef AMIGA
  4782.         /* handle ":tmp" as absolute path */
  4783.         || file_to_find[0] == ':'
  4784. #endif
  4785.        )
  4786.     {
  4787.     /*
  4788.      * Absolute path, no need to use "path_option".
  4789.      * If this is not a first call, return NULL.  We already returned a
  4790.      * filename on the first call.
  4791.      */
  4792.     if (first == TRUE)
  4793.     {
  4794.         int        l;
  4795.         int        run;
  4796.  
  4797.         if (path_with_url(file_to_find))
  4798.         {
  4799.         file_name = vim_strsave(file_to_find);
  4800.         goto theend;
  4801.         }
  4802.  
  4803.         /* When FNAME_REL flag given first use the directory of the file.
  4804.          * Otherwise or when this fails use the current directory. */
  4805.         for (run = 1; run <= 2; ++run)
  4806.         {
  4807.         l = (int)STRLEN(file_to_find);
  4808.         if (run == 1 && rel_to_curdir && (options & FNAME_REL)
  4809.                       && STRLEN(rel_fname) + l < MAXPATHL)
  4810.         {
  4811.             STRCPY(NameBuff, rel_fname);
  4812.             STRCPY(gettail(NameBuff), file_to_find);
  4813.             l = (int)STRLEN(NameBuff);
  4814.         }
  4815.         else
  4816.         {
  4817.             STRCPY(NameBuff, file_to_find);
  4818.             run = 2;
  4819.         }
  4820.  
  4821.         /* When the file doesn't exist, try adding parts of
  4822.          * 'suffixesadd'. */
  4823.         buf = curbuf->b_p_sua;
  4824.         for (;;)
  4825.         {
  4826.             if (mch_getperm(NameBuff) >= 0
  4827.                     && (!need_dir || mch_isdir(NameBuff)))
  4828.             {
  4829.             file_name = vim_strsave(NameBuff);
  4830.             goto theend;
  4831.             }
  4832.             if (*buf == NUL)
  4833.             break;
  4834.             copy_option_part(&buf, NameBuff + l, MAXPATHL - l, ",");
  4835.         }
  4836.         }
  4837.     }
  4838.     }
  4839.     else
  4840.     {
  4841.     /*
  4842.      * Loop over all paths in the 'path' or 'cdpath' option.
  4843.      * When "first" is set, first setup to the start of the option.
  4844.      * Otherwise continue to find the next match.
  4845.      */
  4846.     if (first == TRUE)
  4847.     {
  4848.         /* vim_findfile_free_visited can handle a possible NULL pointer */
  4849.         vim_findfile_free_visited(search_ctx);
  4850.         dir = path_option;
  4851.         did_findfile_init = FALSE;
  4852.     }
  4853.  
  4854.     for (;;)
  4855.     {
  4856.         if (did_findfile_init)
  4857.         {
  4858.         ff_search_ctx->ffsc_need_dir = need_dir;
  4859.         file_name = vim_findfile(search_ctx);
  4860.         ff_search_ctx->ffsc_need_dir = FALSE;
  4861.         if (file_name != NULL)
  4862.             break;
  4863.  
  4864.         did_findfile_init = FALSE;
  4865.         }
  4866.         else
  4867.         {
  4868.         char_u  *r_ptr;
  4869.  
  4870.         if (dir == NULL || *dir == NUL)
  4871.         {
  4872.             /* We searched all paths of the option, now we can
  4873.              * free the search context. */
  4874.             vim_findfile_cleanup(search_ctx);
  4875.             search_ctx = NULL;
  4876.             break;
  4877.         }
  4878.  
  4879.         if ((buf = alloc((int)(MAXPATHL))) == NULL)
  4880.             break;
  4881.  
  4882.         /* copy next path */
  4883.         buf[0] = 0;
  4884.         copy_option_part(&dir, buf, MAXPATHL, " ,");
  4885.  
  4886. #ifdef FEAT_PATH_EXTRA
  4887.         /* get the stopdir string */
  4888.         r_ptr = vim_findfile_stopdir(buf);
  4889. #else
  4890.         r_ptr = NULL;
  4891. #endif
  4892.         search_ctx = vim_findfile_init(buf, file_to_find, r_ptr, 100,
  4893.                    FALSE, TRUE, search_ctx, FALSE, rel_fname);
  4894.         if (search_ctx != NULL)
  4895.             did_findfile_init = TRUE;
  4896.         vim_free(buf);
  4897.         }
  4898.     }
  4899.     }
  4900.     if (file_name == NULL && (options & FNAME_MESS))
  4901.     {
  4902.     if (first == TRUE)
  4903.     {
  4904.         if (need_dir)
  4905.         EMSG2(_("E344: Can't find directory \"%s\" in cdpath"),
  4906.             file_to_find);
  4907.         else
  4908.         EMSG2(_("E345: Can't find file \"%s\" in path"),
  4909.             file_to_find);
  4910.     }
  4911.     else
  4912.     {
  4913.         if (need_dir)
  4914.         EMSG2(_("E346: No more directory \"%s\" found in cdpath"),
  4915.             file_to_find);
  4916.         else
  4917.         EMSG2(_("E347: No more file \"%s\" found in path"),
  4918.             file_to_find);
  4919.     }
  4920.     }
  4921.  
  4922. theend:
  4923. #ifdef AMIGA
  4924.     proc->pr_WindowPtr = save_winptr;
  4925. #endif
  4926.     return file_name;
  4927. }
  4928.  
  4929. #endif /* FEAT_SEARCHPATH */
  4930.  
  4931. /*
  4932.  * Change directory to "new_dir".  If FEAT_SEARCHPATH is defined, search
  4933.  * 'cdpath' for relative directory names, otherwise just mch_chdir().
  4934.  */
  4935.     int
  4936. vim_chdir(new_dir)
  4937.     char_u    *new_dir;
  4938. {
  4939. #ifndef FEAT_SEARCHPATH
  4940.     return mch_chdir((char *)new_dir);
  4941. #else
  4942.     char_u    *dir_name;
  4943.  
  4944.     dir_name = find_directory_in_path(new_dir, (int)STRLEN(new_dir),
  4945.                         FNAME_MESS, curbuf->b_ffname);
  4946.     if (dir_name == NULL)
  4947.     return -1;
  4948.     return mch_chdir((char *)dir_name);
  4949. #endif
  4950. }
  4951.  
  4952. /*
  4953.  * Get user name from machine-specific function and cache it.
  4954.  * Returns the user name in "buf[len]".
  4955.  * Some systems are quite slow in obtaining the user name (Windows NT).
  4956.  * Returns OK or FAIL.
  4957.  */
  4958.     int
  4959. get_user_name(buf, len)
  4960.     char_u    *buf;
  4961.     int        len;
  4962. {
  4963.     static char_u    *name = NULL;
  4964.  
  4965.     if (name == NULL)
  4966.     {
  4967.     if (mch_get_user_name(buf, len) == FAIL)
  4968.         return FAIL;
  4969.     name = vim_strsave(buf);
  4970.     }
  4971.     else
  4972.     STRNCPY(buf, name, len);
  4973.     return OK;
  4974. }
  4975.  
  4976. #ifndef HAVE_QSORT
  4977. /*
  4978.  * Our own qsort(), for systems that don't have it.
  4979.  * It's simple and slow.  From the K&R C book.
  4980.  */
  4981.     void
  4982. qsort(base, elm_count, elm_size, cmp)
  4983.     void    *base;
  4984.     size_t    elm_count;
  4985.     size_t    elm_size;
  4986.     int (*cmp) __ARGS((const void *, const void *));
  4987. {
  4988.     char_u    *buf;
  4989.     char_u    *p1;
  4990.     char_u    *p2;
  4991.     int        i, j;
  4992.     int        gap;
  4993.  
  4994.     buf = alloc((unsigned)elm_size);
  4995.     if (buf == NULL)
  4996.     return;
  4997.  
  4998.     for (gap = elm_count / 2; gap > 0; gap /= 2)
  4999.     for (i = gap; i < elm_count; ++i)
  5000.         for (j = i - gap; j >= 0; j -= gap)
  5001.         {
  5002.         /* Compare the elements. */
  5003.         p1 = (char_u *)base + j * elm_size;
  5004.         p2 = (char_u *)base + (j + gap) * elm_size;
  5005.         if ((*cmp)((void *)p1, (void *)p2) <= 0)
  5006.             break;
  5007.         /* Exchange the elemets. */
  5008.         mch_memmove(buf, p1, elm_size);
  5009.         mch_memmove(p1, p2, elm_size);
  5010.         mch_memmove(p2, buf, elm_size);
  5011.         }
  5012.  
  5013.     vim_free(buf);
  5014. }
  5015. #endif
  5016.  
  5017. #if defined(FEAT_EX_EXTRA) || defined(FEAT_CMDL_COMPL) || defined(PROTO)
  5018. /*
  5019.  * Sort an array of strings.
  5020.  */
  5021. static int
  5022. #ifdef __BORLANDC__
  5023. _RTLENTRYF
  5024. #endif
  5025. sort_compare __ARGS((const void *s1, const void *s2));
  5026.  
  5027.     static int
  5028. #ifdef __BORLANDC__
  5029. _RTLENTRYF
  5030. #endif
  5031. sort_compare(s1, s2)
  5032.     const void    *s1;
  5033.     const void    *s2;
  5034. {
  5035.     return STRCMP(*(char **)s1, *(char **)s2);
  5036. }
  5037.  
  5038.     void
  5039. sort_strings(files, count)
  5040.     char_u    **files;
  5041.     int        count;
  5042. {
  5043.     qsort((void *)files, (size_t)count, sizeof(char_u *), sort_compare);
  5044. }
  5045. #endif
  5046.  
  5047. #if !defined(NO_EXPANDPATH) || defined(PROTO)
  5048. /*
  5049.  * Compare path "p[]" to "q[]".
  5050.  * Return value like strcmp(p, q), but consider path separators.
  5051.  */
  5052.     int
  5053. pathcmp(p, q)
  5054.     const char *p, *q;
  5055. {
  5056.     int        i;
  5057.     const char    *s;
  5058.  
  5059.     for (i = 0; ; ++i)
  5060.     {
  5061.     /* End of "p": check if "q" also ends or just has a slash. */
  5062.     if (p[i] == NUL)
  5063.     {
  5064.         if (q[i] == NUL)  /* full match */
  5065.         return 0;
  5066.         s = q;
  5067.         break;
  5068.     }
  5069.  
  5070.     /* End of "q": check if "p" just has a slash. */
  5071.     if (q[i] == NUL)
  5072.     {
  5073.         s = p;
  5074.         break;
  5075.     }
  5076.  
  5077.     if (
  5078. #ifdef CASE_INSENSITIVE_FILENAME
  5079.         TO_UPPER(p[i]) != TO_UPPER(q[i])
  5080. #else
  5081.         p[i] != q[i]
  5082. #endif
  5083. #ifdef BACKSLASH_IN_FILENAME
  5084.         /* consider '/' and '\\' to be equal */
  5085.         && !((p[i] == '/' && q[i] == '\\')
  5086.             || (p[i] == '\\' && q[i] == '/'))
  5087. #endif
  5088.         )
  5089.     {
  5090.         if (vim_ispathsep(p[i]))
  5091.         return -1;
  5092.         if (vim_ispathsep(q[i]))
  5093.         return 1;
  5094.         return ((char_u *)p)[i] - ((char_u *)q)[i];        /* no match */
  5095.     }
  5096.     }
  5097.  
  5098.     /* ignore a trailing slash, but not "//" or ":/" */
  5099.     if (s[i + 1] == NUL && i > 0 && !vim_ispathsep(s[i - 1])
  5100. #ifdef BACKSLASH_IN_FILENAME
  5101.         && (s[i] == '/' || s[i] == '\\')
  5102. #else
  5103.         && s[i] == '/'
  5104. #endif
  5105.        )
  5106.     return 0;   /* match with trailing slash */
  5107.     if (s == q)
  5108.     return -1;        /* no match */
  5109.     return 1;
  5110. }
  5111. #endif
  5112.  
  5113. #if defined(FEAT_PRINTER) || defined(PROTO)
  5114. /*
  5115.  * Parse a list of options in the form
  5116.  * option:value,option:value,option:value
  5117.  *
  5118.  * "value" can start with a number which is parsed out, e.g.
  5119.  * margin:12mm
  5120.  *
  5121.  * Returns error message for an illegal option, NULL otherwise.
  5122.  * Only used for the printer at the moment...
  5123.  */
  5124.     char_u *
  5125. parse_list_options(option_str, table, table_size)
  5126.     char_u        *option_str;
  5127.     option_table_T    *table;
  5128.     int            table_size;
  5129. {
  5130.     char_u    *stringp;
  5131.     char_u    *colonp;
  5132.     char_u    *commap;
  5133.     char_u    *p;
  5134.     int        idx = 0;        /* init for GCC */
  5135.     int        len;
  5136.  
  5137.     for (idx = 0; idx < table_size; ++idx)
  5138.     table[idx].present = FALSE;
  5139.  
  5140.     /*
  5141.      * Repeat for all comma separated parts.
  5142.      */
  5143.     stringp = option_str;
  5144.     while (*stringp)
  5145.     {
  5146.     colonp = vim_strchr(stringp, ':');
  5147.     if (colonp == NULL)
  5148.         return (char_u *)N_("Missing colon");
  5149.     commap = vim_strchr(stringp, ',');
  5150.     if (commap == NULL)
  5151.         commap = option_str + STRLEN(option_str);
  5152.  
  5153.     len = (int)(colonp - stringp);
  5154.  
  5155.     for (idx = 0; idx < table_size; ++idx)
  5156.         if (STRNICMP(stringp, table[idx].name, len) == 0)
  5157.         break;
  5158.  
  5159.     if (idx == table_size)
  5160.         return (char_u *)N_("Illegal component");
  5161.  
  5162.     p = colonp + 1;
  5163.     table[idx].present = TRUE;
  5164.  
  5165.     if (table[idx].hasnum)
  5166.     {
  5167.         if (!isdigit(*p))
  5168.         return (char_u *)N_("digit expected");
  5169.  
  5170.         table[idx].number = getdigits(&p); /*advances p*/
  5171.     }
  5172.  
  5173.     table[idx].string = p;
  5174.     table[idx].strlen = (int)(commap - p);
  5175.  
  5176.     stringp = commap;
  5177.     if (*stringp == ',')
  5178.         ++stringp;
  5179.     }
  5180.  
  5181.     return NULL;
  5182. }
  5183.  
  5184.  
  5185. #endif /*FEAT_PRINTER*/
  5186.